Archive for the ‘nginx’ tag
Client-IP Problem bei Reverse-Proxy-Betrieb
In einem meiner letzten Artikel schrieb ich ja bereits über Reverse-Proxies. Der Reverse-Proxy nimmt die Verbindung vom Client (Browser) entgegen, dann kann er entweder selbst den Request bedienen (statische Dateien von der lokalen Platte oder aus dem Cache), oder er verbindet sich zu einem der Backend-Webserver, ruft dort die geforderte Datei ab, und sendet sie dem Client zurück.
Ein Problem entsteht nun auf dem Backend-Webserver: Alle Requests kommen vom Reverse-Proxy. Wenn nun in den PHP-Scripten die Client-IP-Adresse verwendet wird, steht darin die IP des Reverse-Proxies.
Betroffen ist in diesem Fall die PHP-Variable $_SERVER[‚REMOTE_ADDR‘] als auch das Apache-Log, denn dort taucht auch immer nur die IP des Reverse-Proxy auf.
127.0.0.1 - - [03/Oct/2009:10:45:24 +0200] "GET /phpinfo.php HTTP/1.0" 200 7800 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0; de; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 (.NET CLR 3.5.30729) FirePHP/0.3"
127.0.0.1 deshalb, da ich direkt auf der Linux-Maschine sowohl den nginx als auch den Apache laufen habe.
Da gibt es natürlich Lösungen. Zuerst einmal müssen wir die Client-IP irgendwie an den Backend-Webserver übergeben. Dafür gibt es den Header „X_FORWARDED_FOR“, da wird der nginx die Client-IP reinschreiben.
Im nginx muss dann folgendes gesetzt werden:
location / { proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_redirect off; ........
Ein phpinfo() liefert dann die korrekte Client-IP in X_FORWARDED_FOR (34 ist der Server, 33 der Client):
Nun installieren wir noch ein Apache-Modul. Dieses Modul sorgt dafür, dass in die Variable $_SERVER[‚REMOTE_ADDR‘] der Wert aus X-FORWARDED-FOR geschreiben wird, damit wir keine PHP-Scripte anpassen müssen. Außerdem sorgt dieses Modul dafür, dass im Apache-Log dieser Wert auftaucht.
Das Module, das es für diese Aufgabe gibt, lautet „mod_rpaf“. Einfach danach googlen, downloaden und in der Apache-Konfiguration laden. Oder unter Linux:
sudo apt-get install libapache2-mod-rpaf
Noch kurz konfigurieren /etc/apache2/mods-available/rpaf.conf:
<IfModule mod_rpaf.c> RPAFenable On RPAFsethostname On RPAFproxy_ips 127.0.0.1 </IfModule>
Das Ergebnis sieht dann so aus:
192.168.1.33 - - [03/Oct/2009:10:47:23 +0200] "GET /phpinfo.php HTTP/1.0" 200 7808 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0; de; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 (.NET CLR 3.5.30729) FirePHP/0.3"
Möchte man das Modul nicht installieren, muß man überall in seinen PHP-Scripten die Variable $_SERVER[‚X_FORWARDED_FOR‘] statt $_SERVER[‚REMOTE_ADDR‘] nutzen, und das Apache-Log anpassen:
LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
Damit hätten wir das Problem auch gelöst, überall steht nun die Client-IP zur Verfügung, die Anwendungen und Logs laufen wieder korrekt.
Bessere Performance mit einem Reverse Proxy
In diesem Artikel geht es nicht um PHP, sondern darum, wie man ein PHP-Applikation via Webserver einer großen Besuchermenge zugänglich macht. Der Standard ist aktuell ein Apache (1.3 oder 2.x), der PHP beherrscht (via mod_php oder FastCGI). Darüber kann man dann wunderbar die Webseiten „serven“.
Doch was tut man, wenn durch eine große Besucheranzahl der Webserver droht, in die Knie zu gehen? Der Apache ist sehr vielseitig, reich an Features, stabil und eigentlich nicht wegzudenken. Doch genau diese Vielseitigkeit und der Feature-Reichtum sind ein Nachteil. Er verbraucht außerdem sehr viel Speicher bei hoher Belastung, sprich vielen tausend Verbindungen.
Deshalb stellt man einen Reverse-Proxy vor den Apache-Webserver. Häufig können diese Proxys auch gleich noch die SSL-Verbindung terminieren, Cachen, und mehr oder minder umfangreiches Loadbalancing.
Einige Bereiche einer Webseite benötigen keinen voll ausgestatteten Apache-Boliden, es reicht ein einfacher, kleinerer Webserver. Dazu gehören alle statischen Inhalte, wie Bilder, Javascripte, CSS und statisches HTML.
Außerdem bereiten langsame Clients Probleme bei großen Webseiten. Wenn viele langsame Clients die Apache-Prozesse am Leben halten, weil die Bytes nur langsam durch das Netz tröpfeln, können andere Requests nicht bedient werden. Ein leichtgewichtiger Reverse-Proxy löst dieses Problem.
Sicher ist euch Squid ein Begriff. Squid kann sowohl als Proxy und auch als Reverse Proxy genutzt werden. Squid ist aber so umfangreich und schwer zu konfigurieren, dass er kaum zum Einsatz kommt als Reverse Proxy.
lighty (lighttpd) dürfte auch vielen bekannt vorkommen. Er hat sehr wenig Ressourcenanforderungen an CPU und Speicher, läuft auf High-Traffic-Seiten wie Youtube, Wikipedia, Pirate Bay, Imageshack und weiteren.
Ein weiterer interessanter leichtgewichtiger Webserver ist nginx (gesprochen: engine-x). nginx ist neuer, bietet auch eine großartige Leistung wie Lighty (je nach Einsatzgebiet unterschiedlich, aber auf gleichem Niveau; auf jeden Fall Klassen besser als Apache). Seiten wie WordPress.com, Github, SourceForge und vielen weiteren werden von nginx bereitgestellt. Mehr als 5% aller Webseiten laufen mittlerweile durch einen nginx!
Hier scheiden sich die Geister, welcher von beiden nun besser ist. Wenn man sich mal 1-2 Stunden im Internet umschaut, sind 60% für nginx und 40% schwören auf lighttpd. Das größte Problem des Lighty ist wohl sein Memory-Leak-Problem, jedenfalls liest man das recht häufig von Umsteigern. Deshalb verlassen viele nun das Lager in Richtung nginx.
Im Anhang habe ich auch noch einige Seiten aufgelistet, die sich mit Vergleichen (Features, Performance) beschäftigt haben.
Die größten Vorteile: sehr geringer Speicherverbrauch, der auch nicht wächst bei sehr vielen Verbindungen, da es sich um eine „event-driven architecture“ handelt, anders als der Prozess/Thread-getriebene Apache. Ideal für kleine statische Dateien und als Reverse Proxy.
Mit nginx hat man auch einen Loadbalancer, der RoundRobin, weighted RoundRobin, Heartbeat-Funktionalität(er merkt, wenn ein Backend-Server tot ist) uvm bietet. Er kann selbst Dateien zur Verfügung stellen oder aber an einen/mehrere Apache weitergeben. Man kann ihn auch zum Cachen benutzen, er unterstützt nativ den Memcached.
Hier gibt es auch einen schönen Bericht darüber, wie nginx als IMAP/POP/WEB/SMTP Proxy betrieben werden kann. 10.000 IMAP-Verbindungen, einige davon SSL, und dann nur 10% CPU Last finde ich beeindruckend.
Man kann auch den kompletten Apache abschaffen und PHP unter nginx betreiben, hier eine kleine Anleitung für Debian. Hier ist noch eine sehr schöne Anleitung, die alle Funktionen beleuchtet incl. Konfigurationszeilen. Es gibt viele dutzend Module, mit denen man nginx erweitern kann, dazu einfach das englische nginx-Wiki durchstöbern.
Ich habe selbst noch keinen nginx laufen, da ich keinerlei Webseite im Internet betreibe, wo sich der „Aufwand“ eines Reverse Proxy lohnt. Aber in naher Zukunft werde ich wahrscheinlich mit dem Thema konfrontiert, eine High-Traffic-Seite mit aufbauen zu können. Und da werden wir sicher einen Reverse-Proxy einsetzen.
Falls jemand Erfahrungen im High-Traffic-Bereich hat, möge er gern seine Meinung dazu kundtun, ich würd mich freuen!
—————————————
Es gibt viele Vergleiche zwischen Apache, Lighty und nginx. Hier einige Quellen (googlen geht natürlich auch):
http://www.wikivs.com/wiki/Lighttpd_vs_nginx
http://hostingfu.com/article/nginx-vs-lighttpd-for-a-small-vps
http://royal.pingdom.com/2008/04/17/alternative-web-servers-compared-lighttpd-nginx-litespeed-and-zeus/
http://barry.wordpress.com/2008/04/28/load-balancer-update/ incl. Kommentare
http://www.joeandmotorboat.com/2008/02/28/apache-vs-nginx-web-server-performance-deathmatch/