June 26, 2013

Wie du mit nginx deinen Linuxserver in 5 Minuten auf Hochlast trimmst

Es ist soweit: Nach Facebook, Sourceforge und Intel läuft auch kushellig.de nicht mehr mit Apache, sondern mit nginx :). Nachdem meine vServer-Variante bei netcup nicht mehr weitergeführt wird, hatte ich 1 Monat Wechselfrist auf den neuen Server. Da ich von Apache eh nicht so begeistert war, was die Performance anging, habe ich mich nach Webserveralternativen umgesehen. Höchste Priorität hatte dabei die Performance deshalb, weil die Specs des vServers doch eher bescheiden sind:

  • 2x 2Ghz CPU
  • 2GB RAM

Für 9 Euro im Monat und ein paar WordPress-Blogs ist das völlig ausreichend, allerdings saugt Apache gewaltig an den Resourcen. Apache ist aufgrund seiner Architektur und Arbeitsweise doch eher der Traktor unter den Webservern. Besonders bei der Auslieferung von statischen Dateien wie Bildern, JS oder CSS und bei Multi-Concurrency-Requests – also vielen gleichzeitigen Requests – fällt die Trägheit auf. Da ein üblicher Seitenaufruf eines Users nur eine dynamische – z.B. PHP – Datei, aber viele statische Dateien wie CSS, mehrere Javascripts, viele Bilder abfragt, tut das natürlich weh.

Für die Ungeduldigen: Direkt zur Installation

Workerprozesse vs. Events

Also, kurz nach Alternativen gegooglet, und nginx gefunden. nginx ist im Vergleich zu Apache nicht Workerprozess-, sondern Eventbasierend. Apache nutzt für jeden Request einen Workerprozess bzw. eigene Threads. So ein Prozess enthält immer das komplette Bundle aller installierten Apache-Module, unabhängig vom Request bzw. Requestfile. Das wiederum heißt, an jeden Prozess wird unter anderem auch immer das PHP Modul gebunden, egal, ob eine PHP-Datei, ein Bild oder eine Textdatei angefragt wurde. Dadurch jeder Requestprozess locker 30+MB im RAM inne, und das ist noch vorsichtig geschätzt.

nginx geht einen anderen Weg: Events. Anstatt für jeden Request einen eigenen Prozess zu starten bzw. zu nutzen, frühstückt nginx die Requests mit Events ab. Jeder Request ist dabei ein Event. Dadurch, dass nur wenige Prozesse und Threads auf Events lauschen, ist nginx viel resourcenfreundlicher. So braucht nginx für 10.000 gleichzeitige HTTP-Requests nur ca. 2,5MB RAM.

Während nginx nun Request für Request bzw. Event für Event seine Warteschlange durchballert, erstellt Apache für jeden Request einen neuen Workerprozess oder -thread. Das hat zur Folge, dass der Apache irgendwann an seine Grenzen stösst und in die Knie geht (Slashdot-Effekt).

Benchmark Apache vs. nginx

Eigene Tests mit ApacheBench auf einem Rootserver (Intel® Xeon® E3-1245 Quad-Core, 32 GB ECC RAM, 3 TB SATA 6 Gb/s HDD 7200 rpm) mit 10.000 Requests, Concurrencylevel 1.000, haben den Apache nach 4.200 Requests zur Aufgabe gezwungen. nginx hingegen hat auf dem gleichen Server die 10.000 Anfragen auf die gleiche Datei locker abgearbeitet.

Bei einem weiteren Test mit einer .jpg Datei und nur 100 gleichzeitigen Requests hat nginx 10x soviele Anfragen wie Apache in der gleichen Zeit geschafft.

nginx: Installation

Entlastung von Apache: nginx als Reverse Proxy

Es ist möglich, nginx als Reverse Proxy vor den Apache zu schalten. Dadurch muss nichts an der PHP Konfiguration geändert werden. nginx entscheidet dann, ob es selbst den Request bearbeitet (z.B. bei nicht-PHP-Dateien) oder den Request direkt an Apache weiterleitet. Ein Tutorial dazu findest du hier: Nginx als Reverse Proxy für statische Inhalte vor Apache.

nginx: Installation mit PHP als Apacheablöse

Ich habe mich hingegen dazu entschieden, Apache komplett zu verbannen und nur auf nginx zu setzen.

Die Installation ist wirklich unkompliziert (ca. 2 Minuten), wenn man ein funktionierendes Tutorial hat. Apache kann man erst einmal nebenher weiterlaufen lassen.

Step 1: apache2 entfernen

sudo apt-get purge apache2

Step 2: Pakete installieren

sudo apt-get install nginx php7.0-fpm

Damit installierst du nginx und php-fpm. php-fpm ist ein FastCGI Prozess Manager.

Das war’s, nginx läuft auf deinem Webserver 🙂 Nur noch wenige Steps, bis deine Website angezeigt wird.

Step 3: php-fpm auf TCP lauschen lassen

sudo vim /etc/php/7.0/fpm/pool.d/www.conf

Ersetze die Zeile

listen = /run/php/php7.0-fpm.sock

mit

listen = 127.0.0.1:9000

Danach php-fpm neustarten>

sudo service php7.0-fpm restart

Step 4: Vhost anlegen

Beispielhaft poste ich hier das Vorgehen, um die Vhost-Datei für ein WordPressblog anzulegen.

Vhost-Datei anlegen:

sudo vim /etc/nginx/sites-available/meinedomain.de

Inhalt:

# Upstream to abstract backend connection(s) for php
upstream deinedomainupstream {
        server 127.0.0.1:9000;
}
server {
    listen 80;
    root /pfad/zum/wordpress;
    index index.php index.html index.htm;
    server\_name deinedomain.de;
    charset UTF-8;
    location / {
        try\_files $uri/ /index.php?$args;
    }
    location ~ \\.php$ {
        try\_files $uri =404;
        fastcgi\_split\_path\_info ^(.+\\.php)(/.+)$;
        fastcgi\_pass deinedomainupstream;
        fastcgi\_index index.php;
        include fastcgi.conf;
                fastcgi\_buffer\_size 128k;
                fastcgi\_buffers 256 16k;
                fastcgi\_busy\_buffers\_size 256k;
                fastcgi\_temp\_file\_write\_size 256k;
    }
    location ~\* \\.(js|css|png|jpg|jpeg|gif|ico|eot|otf|ttf|woff)$ {
        add\_header Access-Control-Allow-Origin \*;
        access\_log off; log\_not\_found off; expires 30d;
    }
    location = /robots.txt { access\_log off; log\_not\_found off; }
    location ~ /\\. { deny all; access\_log off; log\_not\_found off; }
}
server {
    server\_name www.deinedomain.de;
    return 301 $scheme://deinedomain.de$request\_uri;

}

Vhost-Datei enablen:

sudo ln -s /etc/nginx/sites-available/meinedomain.de /etc/nginx/sites-enabled/meinedomain.de

nginx restarten:

sudo service nginx restart

Und voilà, du hast ein laufendes WordPress mit nginx und php-fpm. Möge der Traffic kommen!

Ist noch etwas unklar? Fehlt dir etwas in diesem Artikel? Hilf mir, ihn zu verbessern, und hinterlasse unten bitte ein Kommentar oder bewerte ihn!