Apache Tomcat drosselt nach 300 Verbindungen


16

Wir haben einen Apache-Webserver vor Tomcat, der auf EC2 gehostet wird. Der Instanztyp ist mit 34 GB Speicher besonders groß.

Unsere Anwendung beschäftigt sich mit vielen externen Webservices und wir haben einen sehr miesen externen Webservice, der fast 300 Sekunden benötigt, um auf Anfragen während der Stoßzeiten zu antworten.

Während der Stoßzeiten drosselt der Server bei nur etwa 300 httpd-Prozessen. ps -ef | grep httpd | wc-l = 300

Ich habe gegoogelt und zahlreiche Vorschläge gefunden, aber nichts scheint zu funktionieren. Im Folgenden sind einige Einstellungen aufgeführt, die ich vorgenommen habe und die direkt aus Online-Ressourcen entnommen wurden.

Ich habe die Grenzen von max connection und max clients in Apache und Tomcat erhöht. Hier sind die Konfigurationsdetails:

//Apache

   <IfModule prefork.c>
    StartServers 100
    MinSpareServers 10
    MaxSpareServers 10
    ServerLimit 50000
    MaxClients 50000
    MaxRequestsPerChild 2000
    </IfModule>

//Kater

    <Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
           connectionTimeout="600000"
           redirectPort="8443"
           enableLookups="false" maxThreads="1500"
           compressableMimeType="text/html,text/xml,text/plain,text/css,application/x-javascript,text/vnd.wap.wml,text/vnd.wap.wmlscript,application/xhtml+xml,application/xml-dtd,application/xslt+xml"
           compression="on"/>

//Sysctl.conf

 net.ipv4.tcp_tw_reuse=1
 net.ipv4.tcp_tw_recycle=1
 fs.file-max = 5049800
 vm.min_free_kbytes = 204800
 vm.page-cluster = 20
 vm.swappiness = 90
 net.ipv4.tcp_rfc1337=1
 net.ipv4.tcp_max_orphans = 65536
 net.ipv4.ip_local_port_range = 5000 65000
 net.core.somaxconn = 1024

Ich habe zahlreiche Vorschläge ausprobiert, aber vergebens. Wie kann ich das beheben? Ich bin sicher, m2xlarge Server sollte mehr Anfragen als 300 bedienen, wahrscheinlich kann ich mit meiner Konfiguration etwas falsch machen.

Der Server drosselt nur zu Spitzenzeiten und wenn 300 gleichzeitige Anforderungen auf die Antwort des Webservices [300 Sekunden verzögert] warten.

Ich habe gerade die TCP-Verbindungen mit netstat überwacht

Ich habe ungefähr 1000 Verbindungen im TIME_WAIT-Status gefunden, keine Ahnung, was dies für die Leistung bedeuten würde. Ich bin mir sicher, dass es das Problem noch verschlimmert.

Ausgabe von TOP

 8902  root      25   0 19.6g 3.0g  12m S  3.3  8.8  13:35.77 java
 24907 membase   25   0  753m 634m 2528 S  2.7  1.8 285:18.88 beam.smp
 24999 membase   15   0  266m 121m 3160 S  0.7  0.3  51:30.37 memcached
 27578 apache    15   0  230m 6300 1536 S  0.7  0.0   0:00.03 httpd
 28551 root      15   0 11124 1492  892 R  0.3  0.0   0:00.25 top


 Output of free -m
 total       used       free     shared    buffers    cached
 35007       8470       26536    0          1         61
 8407        26599
 15999       15         15984

 output of iostat
 avg-cpu:  %user   %nice %system %iowait  %steal   %idle
      26.21    0.00    0.48    0.13    0.02   73.15

Device:            tps   Blk_read/s   Blk_wrtn/s   Blk_read   Blk_wrtn
sda1             14.36         4.77       329.37    9005402  622367592
sdb               0.00         0.00         0.00       1210         48

Auch in der Spitzenzeit gibt es ca. 10-15k TCP-Verbindungen zum membase-Server [local].

EINIGE FEHLER IM MODJK-PROTOKOLL, ich hoffe, das wirft ein Licht auf das Problem.

[Wed Jul 11 14:39:10.853 2012] [8365:46912560456400] [error]         ajp_send_request::jk_ajp_common.c (1630): (tom2) connecting to backend failed. Tomcat is probably not started or is listening on the wrong port (errno=110)
[Wed Jul 11 14:39:18.627 2012] [8322:46912560456400] [error] ajp_send_request::jk_ajp_common.c (1630): (tom2) connecting to backend failed. Tomcat is probably not started or is listening on the wrong port (errno=110)
[Wed Jul 11 14:39:21.358 2012] [8351:46912560456400] [error] ajp_get_reply::jk_ajp_common.c (2118): (tom1) Tomcat is down or refused connection. No response has been sent to the client (yet)
[Wed Jul 11 14:39:22.640 2012] [8348:46912560456400] [error] ajp_get_reply::jk_ajp_common.c (2118): (tom1) Tomcat is down or refused connection. No response has been sent to the client (yet)

~

Worker.properties
workers.tomcat_home=/usr/local/tomcat/
worker.list=loadbalancer
worker.tom1.port=8009
worker.tom1.host=localhost
worker.tom1.type=ajp13
worker.tom1.socket_keepalive=True
worker.tom1.connection_pool_timeout=600
worker.tom2.port=8109
worker.tom2.host=localhost
worker.tom2.type=ajp13
worker.tom2.socket_keepalive=True
worker.tom2.connection_pool_timeout=600
worker.loadbalancer.type=lb
worker.loadbalancer.balanced_workers=tom1,tom2
worker.loadbalancer.sticky_session=True
worker.tom1.lbfactor=1
worker.tom1.socket_timeout=600
worker.tom2.lbfactor=1
worker.tom2.socket_timeout=600

// Gelöst

Vielen Dank für Ihre wertvollen Vorschläge. Ich habe die maxThreads-Einstellungen für den AJP 1.3-Anschluss verpasst. Jetzt scheint alles unter Kontrolle zu sein.

Ich würde auch anfangen, auch basierende Server wie Nginx zu suchen.


Wie sehen Ihre Keepalive-Einstellungen aus?
Tom O'Connor

Welche Art von Fehler erhalten Clients zurück, wenn sie versuchen, eine Seite zu laden?
Shane Madden

1
Haben Sie die maximal zulässige Anzahl offener Dateibeschreibungen für den Apache / httpd-Benutzer erhöht?
Golja

@ Tom My Keep Alive-Einstellungen sind KeepAliveTimeout 10 in httpd.conf
John Titus

3
Wie sieht die Ausgabe von topin diesen Zeiten aus? Wie wäre es free -m? Und zuletzt iostat?
Zypher

Antworten:


13

Haben Sie maxThreads im AJP 1.3 Connector auf Port 8009 erhöht?


1500 ist, was ich pro Kater Instanz habe
John Titus

@ John, sagen Sie, dass für jeden Connector, den Sie angegeben haben, maxThreads = "1500"? Können Sie Ihre Zeilengruppe für den AJP 1.3-Connector (Port 8009) veröffentlichen?
HTTP500,

Vielen Dank für den Hinweis. Es gibt überhaupt keine maxThreads-Einstellung für AJP1.3. Könnte dies der Grund sein?
John Titus

1
Ja, fügen Sie der Zeilengruppe für diesen Connector maxThreads hinzu. Der Standardwert ist 200.
HTTP500

6

Erwägen Sie, einen asynchronen Proxy-Webserver wie nginxoder lighttpdvor Apache einzurichten . Apache stellt den Inhalt synchron bereit, sodass die Mitarbeiter blockiert werden, bis die Clients den generierten Inhalt vollständig heruntergeladen haben (weitere Details hier ). Das Einrichten eines asynchronen (nicht blockierenden) Proxys verbessert normalerweise die Situation dramatisch (ich habe früher die Anzahl der gleichzeitig ausgeführten Apache-Worker von 30 auf 3-5 gesenkt, nginxdie einen Frontend-Proxy verwenden).


5

Ich vermute dein Problem ist bei Kater kein Apache, aus den Logs hast du es trotzdem angezeigt. Wenn der Fehler 110 angezeigt wird, dass versucht wird, eine Verbindung zu Tomcat wiederherzustellen, wird eine Warteschlange mit Verbindungen angezeigt, die nicht mehr in das Listening-Backlog-Setup für den Listening-Socket in Tomcat passen.

From the listen manpage:
   The  backlog  parameter defines the maximum length the queue of pending 
   connections may grow to.  If a connection request arrives with
   the queue full the client may receive an error with an indication
   of ECONNREFUSED or, if the underlying protocol supports  
   retransmission, the request may be ignored so that retries succeed.

Wenn ich raten müsste, würde ich vermuten, dass die überwiegende Mehrheit der HTTP-Anforderungen, wenn der Server "erstickt", blockiert ist und darauf wartet, dass etwas von Tomcat zurückkommt. Ich wette, wenn Sie versuchen, statischen Inhalt abzurufen, der direkt von Apache bereitgestellt wird (anstatt an Tomcat weitergeleitet zu werden), funktioniert dies auch dann, wenn er normalerweise "erstickt".

Ich kenne Tomcat leider nicht, aber gibt es stattdessen eine Möglichkeit, die Einstellungen für die Parallelität zu ändern?

Oh, und Sie müssen möglicherweise auch die Möglichkeit in Betracht ziehen , dass sie die externen Netzwerkdienste , das ist die Anzahl der Verbindungen zu begrenzen , dass es tun Sie bis zu 300, so dass es keinen Unterschied macht , wie viel Manipulieren von Gleichzeitigkeit Sie auf Ihrer Vorderseite tun Wenn praktisch jede Verbindung, die Sie herstellen, auf einer externen Antwort von Webdiensten beruht.

In einem Ihrer Kommentare haben Sie erwähnt, dass die Daten nach 2 Minuten veraltet sind. Ich würde vorschlagen, die Antwort, die Sie von diesem Dienst erhalten, zwei Minuten lang zwischenzuspeichern, um die Anzahl der gleichzeitigen Verbindungen zu verringern, die Sie zum externen Webdienst führen.


2

Der erste Schritt zur Fehlerbehebung besteht darin, den mod_status von Apache zu aktivieren und dessen Bericht zu studieren. Bis Sie dies getan haben, laufen Sie blindlings. Das ist nicht gerecht. ;-)

Die zweite Sache, die ich erwähnen muss (ich selbst möchte keine Antworten auf Fragen bekommen, die ich nicht gestellt habe, aber ...), ist die Verwendung von effizienteren und spezielleren Front-End-Servern wie nginx.

Außerdem haben Sie genau restartApache, oder einfach nur gracefully nachgeladen es? :)


Apache neu gestartet .. keine anmutige Neuladung
John Titus

@johntitus, na ja, mod_statusist sowieso dein Freund. :)
Poige

1

Für jede Art von Unternehmensbereitstellung ist das Prefork-MPM die schlechteste Wahl, die Sie treffen können: Es verschlingt Ressourcen, die für niemanden von Bedeutung sind, und das Neustarten von Threads dauert im Vergleich zu anderen MPMs FÜR IMMER an.

Wechseln Sie mindestens zum Worker- MPM (Apache 2.2 und höher) oder - noch besser - aktualisieren Sie auf die aktuelle stabile Version 2.4.2 mit ihrem Standard- Event- MPM.

In beiden Fällen können problemlos Tausende von gleichzeitigen Verbindungen mit sehr geringem Overhead verarbeitet werden.


danke .. versuchte das auch .. kein Glück. TIME_WAIT-Verbindungen nehmen ständig zu. Der Server reagiert nicht mehr bei 350 Verbindungen
John Titus

1
Ich bin anderer Meinung, dass es die schlechteste Wahl ist - es ist eine schlechte Wahl für diesen Kontext und es ist wahrscheinlich, dass die Probleme durch die Verwendung des Thread-Servers gelindert werden, aber eine bessere Lösung wäre die Verwendung eines ereignisbasierten Servers (nginx oder lighttpd). Der ereignisbasierte Apache ist bei weitem nicht ausgereift genug, um von einer Unternehmensbereitstellung aus betrachtet zu werden.
Symcbean

1

Ich weiß, dass es eine alte Geschichte ist, aber ich habe zwei Bemerkungen.

Für die ServerLimit- Richtlinie gibt es eine fest programmierte Grenze . http://httpd.apache.org/docs/2.2/mod/mpm_common.html#serverlimit Sie werden sehen, dass es maximal 20000 / 200K ist.

Es gibt ein festes Limit für ServerLimit 20000, das auf dem Server kompiliert wurde (für den Prefork MPM 200000). Dies soll böse Effekte durch Tippfehler vermeiden.

2. Anscheinend hat Nodybo erwähnt, dass es eine sehr schlechte Idee ist, diese 2 auf eins zu setzen :

net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_tw_recycle=1

es bedeutet, dass Sie die Zeit vorzeitig wiederverwenden, wissen Sie was? Der Server kann unter hoher Last mit dem falschen Client kommunizieren.

Ich habe einen sehr guten Artikel gefunden, der das erklärt, aber - es ist französisch ;-) http://vincent.bernat.im/fr/blog/2014-tcp-time-wait-state-linux.html


0

extra groß mit 34GB Speicher.

Big Iron ist nicht der richtige Weg, um Webserving zu skalieren. Sie müssen nur die Engpässe beseitigen. Aber selbst mit so viel Speicher vermute ich, dass 50000 Verbindungen die Leistungsfähigkeit des Systems steigern, insbesondere wenn:

Während der Stoßzeiten drosselt der Server bei nur etwa 300 httpd-Prozessen

Es wäre hilfreich, wenn Sie erklären würden, was Sie unter "die Server-Drosseln" verstehen.

Es ist auch sehr seltsam, eine so hohe Grenze für Verbindungen zu haben, aber eine sehr niedrige Grenze für die Hysterese (Min / Max-Ersatzserver).

Obwohl der von Ihnen angegebene Fehlerauszug nicht die Anzeige "Zu viele offene Dateien" enthält, würde ich zunächst die Anzahl der Deskriptoren für geöffnete Dateien und die Einstellungen für ulimit überprüfen.


Server-Drosseln wie in es nicht einmal normale HTML-Dateien reagieren ..
John Titus

Ich habe die maxClients jetzt auf 3000 geändert .. immer noch das gleiche Problem
John Titus

0

Möglicherweise gehen dem Apache-Benutzer die zulässigen Dateihandles aus? Sie haben sie in Ihrem Beitrag überhaupt nicht erwähnt. Wie viele Dateihandles darf Apache derzeit haben?


128192 Datei-Handles
John Titus

0

Dies ist eher wie ein Kommentar, kann aber nicht, da ich weniger Ruf habe. Kam über genau das gleiche Problem wie bei John Titus.

Wir haben den AJP-Stecker gemacht MaxThreads nahe an unser Apache-Thread-Limit gebracht, um das Problem zu beheben.

Um dies zu überwachen, haben wir nach SYN_SENT Hilfe zum netstat-Portstatus mit dem Befehl netstat auf unserem AJP-Port gesucht .

netstat -an | grep :8102 | grep SYN_SENT | wc -l

Dies ging auf 0 zurück, was immer eine große Zahl vor dem in AJP Connector festgelegten MaxThread-Limit war.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.