Optimierung Webserver [Apache2, nginx]


papagei9

New Member
Hallo,

ich hoste seit neuem eine Website (WBB3-Forum), auf dieser etwa 450 Clients mehr oder weniger aktiv sind.

Die Serverauslastung ist seitdem stark gestiegen und ist nicht mehr human.

Das ganze befindet sich auf einem EQ4 bei Hetzner.
Vor dem Apache2 ist nginx als Reverse-Proxy installiert.

Bei nginx ist gzip nicht aktiviert, da das Modul nicht eingebaut ist ...

Die Apache2-Einstellungen sind so:

Code:
Timeout 10
KeepAlive Off
MaxKeepAliveRequests 10
KeepAliveTimeout 5
HostnameLookups off

# prefork MPM
<IfModule mpm_prefork_module>
    StartServers          20
    MinSpareServers       5
    MaxSpareServers      15
    ServerLimit 60
    MaxClients          60
    MaxRequestsPerChild   4000
</IfModule>


Apache Access / Sekunde: 100
Nginx connections: 1'430 active, 1'410 waiting


Weiss jemand, wie ich den Apache2 so optimieren kann, dass die Auslastung wesentlich sinkt?
Es sind immerdurch 60 Apache-Prozesse gestartet.
 
Hallo!

Und wie sieht die nginx Reverse Proxy Konfiguration aus?

mfG
Thorsten
 
Code:
server {

include   /etc/nginx/sites-enabled/urlfilter.inc;
include   /etc/nginx/sites-enabled/useragent.inc;
include   /etc/nginx/sites-enabled/ref.inc;
include   /etc/nginx/sites-enabled/remote_addr.inc;
include   /etc/nginx/sites-enabled/geoip.inc;

location /nginx_status {
  stub_status on;
  access_log off;
}

#location /phpmyadmin {
#  proxy_pass         http://127.0.0.1:82/phpmyadmin;
#  allow 1.1.1.1;
#  deny all;
# }

#location /wi {
#  proxy_pass         http://127.0.0.1:82/;
#  allow 1.1.1.1;
#  deny all;
# }


error_page   403  /403.html;
 location = /403.html {
  root   /var/www/sharedip;
 }

error_page 502 /502.html;
  location = /502.html {
        root /var/www/error;
  }

#    geoip_country  GeoIP.dat;

    listen       46.4.*.*:80;
    listen       46.4.*.*:80;
    listen       46.4.*.*:80;
    server_tokens off;
    access_log  /var/log/nginx/reverse.log;
    error_log /var/log/nginx/errorreverse.log;

    # proxy to Apache 2 and mod_python
    location / {
        proxy_pass         http://127.0.0.1:80/;
        proxy_redirect     off;

        proxy_set_header   Host             $host;
        proxy_set_header   X-Real-IP        $remote_addr;
        proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
        proxy_max_temp_file_size 0;

        client_max_body_size       128m;
        client_body_buffer_size    128k;

        proxy_connect_timeout      180;
        proxy_send_timeout         180;
        proxy_read_timeout         180;

        proxy_buffer_size          16k;
        proxy_buffers              32 32k;
        proxy_busy_buffers_size    64k;
        proxy_temp_file_write_size 64k;
    }
}


server {

include   /etc/nginx/sites-enabled/urlfilter.inc;
include   /etc/nginx/sites-enabled/useragent.inc;
include   /etc/nginx/sites-enabled/ref.inc;
include   /etc/nginx/sites-enabled/remote_addr.inc;
include   /etc/nginx/sites-enabled/geoip.inc;

location /nginx_status {
  stub_status on;
  access_log off;
}
error_page   403  /403.html;
 location = /403.html {
  root   /var/www/sharedip;
 }

error_page 502 /502.html;
  location = /502.html {
        root /var/www/error;
  }

#    geoip_country  GeoIP.dat;

    listen       46.4.*.*:443;
    listen       46.4.*.*:443;
    listen       46.4.*.*:443;
    server_tokens off;

    ssl         on;
    ssl_certificate      /usr/local/nginx/conf/cert.crt;
    ssl_certificate_key  /usr/local/nginx/conf/cert.key;

    access_log  /var/log/nginx/reverse.log;
    error_log /var/log/nginx/errorreverse.log;

    # proxy to Apache 2 and mod_python
    location / {
        proxy_pass         https://127.0.0.1:443/;
        proxy_redirect     off;

        proxy_set_header   Host             $host;
        proxy_set_header   X-Real-IP        $remote_addr;
        proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
        proxy_max_temp_file_size 0;

        client_max_body_size       128m;
        client_body_buffer_size    128k;

        proxy_connect_timeout      180;
        proxy_send_timeout         180;
        proxy_read_timeout         180;

        proxy_buffer_size          16k;
        proxy_buffers              32 32k;
        proxy_busy_buffers_size    64k;
        proxy_temp_file_write_size 64k;
    }
}

So sieht das momentan aus ..
 
Hallo!

Warum hast du das Apache ServerLimit so arg beschnitten? 256 ist hier die Voreinstellung. Dann verstehe ich deine KeepAlive Einstellungen überhaupt nicht. Grundsätzlich ist KeepAlive bei dir aus. Dennoch gibt du explizit MaxKeepAliveRequest mit 10 an (ist meiner Meinung nach viel zu wenig) und KeepAliveTimeout mit 5 Sekunden (kann man drüber streiten bzw. ist abhängig vom Aufbau deiner Seiten).

An diesen Stellen würde ich als ersten optimieren. Interessant wäre ein URL zum apache-status (ExtendedStatus On) wenn der Server unter Last steht.

mfG
Thorsten
 
Ich gehe davon aus, dass auf dem Server nur das angesprochene Forum läuft. Was ist da jetzt genau der funktionale Hintergrund, dass da ein Apache UND nginx läuft?
 
Hallo!

Die landläufige Meinung ist ja, dass ein nginx Reverse Proxy vor einem Apache Webserver immer signifikante Performance Schübe brächte. Das dem eben nicht immer so ist, konnte ich bereits durch eigene Versuche in Erfahrung bringen. Meist macht es wesentlich mehr Sinn, seine Applikationen zu untersuchen und den Apache darauf abzustimmen.

Als zusätzliche Maßnahme kann man darüber nachdenken, beispielsweise statische Inhalte vom nginx ausliefern zu lassen.

PS: Ja, und dann gibt es noch die slowloris Geschichte.

mfG
Thorsten
 
Meine Frage zielte primär darauf ab, warum da überhaupt ein Apache laufen muss. :)

Ich würde hier ja eher auf Nginx + Xcache/APC + PerconaSQL setzen.
 
Hallo,

es sind mehrere Websiten, und ich benutze nginx als ReverseProxy, da ich bereits länger Confixx mit Apache2 verwende, und nicht komplett alles umstellen wollte.
Mit Nginx konnte ich nach der Umstellung eine deutliche Minimierung der Apache-Prozessen sehen.

Danke für den Hinweis mit dem Apache-Status
Apache-Status Seite: http://46.4.67.85/server-status

Ich sehe vorallem, dass ein Chat-Plugin bei einem WBB-Forum viele Requests verursacht. Um diese Zeit ist die Last recht hoch.

Ich habe jetzt noch keine Änderungen an den Einstellungen vorgenommen.
 
Das kann gut der Chat sein, ich würde eher zu einem IRC server raten (da reicht ein mini-vServer) und dem Mibbit Plugin (oder ähnlichem) für das WBB.

Der "Standardchat" von WBB ist ja bei vielen Hostern nicht erlaubt, weil er wahnsinnig Last erzeugt auf dem Server.
 
WebChat und kein Keep-Alive beziehungsweise falschem Keep-Alive ist tödlich.
Alle anderen Nachteile eines solchen Chats kommen noch obendrauf...
 
Okey, danke für die Antworten.

ich habe nun folgende Einstellungen vorgenommen:

Code:
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 10

<IfModule mpm_prefork_module>
    StartServers          20
    MinSpareServers       5
    MaxSpareServers      15
    ServerLimit 256
    MaxClients          256
    MaxRequestsPerChild   4000
</IfModule>
 
Hallo!

Was hat der Server an RAM? Was liefert top? Wie sieht es mit IO wait aus? Laufen da mehrere Chats drauf?

Aktuell rund 90 req/sec. Das ist nicht wenig, aber auch nicht tödlich. Auf jeden Fall würde ich versuchen, Chat(s) und Webseiten zu trennen.

PS: Lies bitte nochmal in der Apache Doku nach, was Keep alive macht.

mfG
Thorsten
 
Okey, danke für die Antwort.

Der Server hat 8 GB RAM, momentan läuft alles wieder recht rund.
IOwait liegt bei 21, top liefert keine ungewöhnlichen Ausgaben.
 
Ich sehe in dieser Konfiguration keinen Sinn.

Klar ist der Nginx in der Front gut, aber dann muss der auch was tun. Was genau macht der denn? Ich sehe nur eine Weiterleitung des gesamten Traffics.

Wenn Du Performance sparen willst, dann solltest Du zumindest Regeln einführen, die statischen Content direkt ausgeben, ohne dass die Zugriffe beim Apache landen.

Und natürlich muss dann auch gzip aktiv sein.

Damit läuft dann schon mal der größte Traffic über Nginx und kommt niemals beim Apache an. Nachteil: Du hast die Zugriffe auch nicht mehr in den Apache Logs, musst also separate Zugriffe per Nginx loggen, wenn Du das unbedingt willst.

Alternativ kannst Du auch einen CDN einrichten und alle statischen Inhalte auf eine CDN Domain umstellen, die auf Amazon CloudFront oder CloudFlare routet.

Mein Hoster hat da richtig tolle Sachen gezaubert. Schnell ist :D
http://www.maxrev.de/forum.htm

Gruß
 
nginx hat sich (bei mir jedenfalls) als reverse proxy richtig gut bewährt, läuft auf einer videorenderingkiste die auch gleichzeitig flash videos für eine facebook app ausliefert perfekt (pro Tag rund 80-90GB Traffic)

Dank cachings von statischen Inhalten wie Videos und Bildern die darüber ausgeliefert werden ist der ganze Spaß noch einen Tick flotter und muss nicht immer erst den Apachen anfragen.

Vorallem bei diversen Attacken hat nginx total die Nase vorn und kann als leistungsstarker reverse proxy punkten.
 
Last edited by a moderator:
Das bezweifelt denke ich auch keiner, aber die hier zitierten Regeln enthalten keine Entlastung für den Apache. Im Gegenteil. Man fördert doch nur Latenzen, wenn man einen Proxy davor schaltet, der keine andere Aufgabe erfüllt als einfach nur den Traffic 1:1 durchzuleiten.

Vielleicht ist ja noch was interessantes in den Dateien, aber von den Dateinamen her abgeleitet, scheint da auch nichts Relevantes drin zu sein, außer dass ein paar Zugriffe blockiert werden:
Code:
include   /etc/nginx/sites-enabled/urlfilter.inc;
include   /etc/nginx/sites-enabled/useragent.inc;
include   /etc/nginx/sites-enabled/ref.inc;
include   /etc/nginx/sites-enabled/remote_addr.inc;
include   /etc/nginx/sites-enabled/geoip.inc;
 
Code:
 location ~* ^.+\.(jpe?g|apk|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js|swf|avi|mp3)$ {
                expires max;
        }
hilft dir so was vielleicht? Kann beliebig erweitert/geändert werden. So ähnlich ist es auch bei mir wobei noch ein paar mehr formate über NginX geliefert werden. PHP ist das einzige was noch an meinen Apachen geschickt wird.
 
Auch diese Regel bringt rein gar nichts. Sie setzt einen expires-Header. Das hat der Apache vorher auch schon gemacht bzw. man kann auch da auf max gehen. Das verhindert aber nicht, dass die Anfragen beim Apache landen. Da musst Du schon mit root arbeiten.
 
Code:
root   /var/www/vhosts/www.***.**k/httpdocs/;

steht natürlich vor der location regel.
danach folgt die proxy_pass regel.

Und in der Tat kommen die statisch definierten aus regel 1 vom nginx und php wird vom apache gehandelt.

EDIT:
Ah jetzt sehe Ich wie du es meintest beim OP sind lediglich redirects definiert dementsprechend wird jede Anfrage nur weitergereicht. Dann hilft natürlich die Regel oben nichts. Es muss also noch das root angeben werden. Stimmt absolut!
 
Last edited by a moderator:
Wenn man es sauber trennen will, dann macht man eine IF Regel auf .php mit proxy_pass und eine ELSE für alles andere mit root. Am einfachsten - aber das geben die wenigsten Softwares her - wenn alle statischen Dateien im gleichen Unterordner liegen. Dann bräuchte man nicht mal regex, sondern kann mit location arbeiten.

IFELSE ist aber bei nginx nicht einfach, weil man dazu den Scriptablauf von oben nach unten beachten muss und für jede Bedingung eine Variable setzen muss. Wir haben eine IF ELSE Regel realisiert auf die Abfragen meiner CDN Domain:
http://mxrv.de/ http://mxrv.de/img/1/maxrev-logo.gif

und der Projektdomain:
http://www.maxrev.de/

Wie man sieht geht die CDN nur bei Deeplinks. Außerdem haben beide Domains die Regel, dass static-Content direkt über nginx rausgeht. Auf die Art kann man im Notfall den CDN ausbauen und es läuft trotzdem.
 

Back
Top