Apache Tomcat s'étouffe après 300 connexions

16

Nous avons un serveur web apache devant Tomcat hébergé sur EC2, le type d'instance est extra large avec 34 Go de mémoire.

Notre application traite de nombreux services Web externes et nous avons un service Web externe très moche qui prend près de 300 secondes pour répondre aux demandes pendant les heures de pointe.

Pendant les heures de pointe, le serveur s'étouffe avec environ 300 processus httpd. ps -ef | grep httpd | wc -l = 300

J'ai googlé et trouvé de nombreuses suggestions, mais rien ne semble fonctionner. Voici quelques configurations que j'ai faites qui sont directement tirées des ressources en ligne.

J'ai augmenté les limites de la connexion maximale et des clients max dans apache et tomcat. voici les détails de configuration:

// apache

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

//matou

    <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

J'ai essayé de nombreuses suggestions mais en vain .. comment y remédier? Je suis sûr que le serveur m2xlarge devrait servir plus de 300 demandes, probablement je peux me tromper avec ma configuration ..

Le serveur ne s'étouffe que pendant les heures de pointe et lorsqu'il y a 300 demandes simultanées en attente de réponse du service Web [300 secondes retardées].

Je surveillais simplement les connexions TCP avec Netstat

j'ai trouvé environ 1000 connexions dans l'état TIME_WAIT, aucune idée de ce que cela signifierait en termes de performances, je suis sûr que cela doit ajouter au problème.

Sortie de 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

Toujours aux heures de pointe, il y a environ 10 à 15 000 connexions TCP au serveur membase [local]

QUELQUES ERREURS DANS MODJK LOG, j'espère que cela jette un peu de lumière sur la question ..

[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

// Résolu

merci à tous pour vos précieuses suggestions .. j'ai raté les paramètres maxThreads pour le connecteur AJP 1.3 .. Maintenant tout semble sous contrôle.

Je commencerais également à regarder des serveurs basés même comme nginx.

john titus
la source
À quoi ressemblent vos paramètres Keepalive?
Tom O'Connor
Quel type d'erreur les clients récupèrent-ils lorsqu'ils tentent de charger une page?
Shane Madden
1
Avez-vous augmenté le nombre maximum autorisé de descriptions de fichiers ouverts pour l'utilisateur apache / httpd?
golja
Les paramètres @Tom My Keep Alive sont KeepAliveTimeout 10 dans httpd.conf
john titus
3
À quoi ressemble la sortie de toppendant ces périodes? Et alors free -m? Et enfin iostat?
Zypher

Réponses:

13

Avez-vous augmenté les maxThreads dans le connecteur AJP 1.3 sur le port 8009?

HTTP500
la source
1500 est ce que j'ai par instance de Tomcat
John Titus
@john, Êtes-vous en train de dire que pour chaque connecteur que vous avez spécifié maxThreads = "1500"? Pouvez-vous publier votre strophe pour le connecteur AJP 1.3 (port 8009)?
HTTP500
merci de l'avoir signalé .. il n'y a aucun paramètre maxThreads pour AJP1.3 du tout .. cela pourrait-il être la raison?
john titus
1
Oui, ajoutez maxThreads à la strophe de ce connecteur. La valeur par défaut est 200.
HTTP500
6

Envisagez de configurer un serveur Web de proxy asynchrone comme nginxou lighttpddevant Apache. Apache sert le contenu de manière synchrone afin que les employés soient bloqués jusqu'à ce que les clients téléchargent le contenu généré dans son intégralité (plus de détails ici ). La configuration d'un proxy asynchrone (non bloquant) améliore généralement la situation de manière spectaculaire (j'avais l'habitude de réduire le nombre de travailleurs Apache exécutés simultanément de 30 à 3-5 utilisant nginxcomme proxy frontal).

Alex
la source
5

Je soupçonne que votre problème est dans tomcat pas apache, à partir des journaux que vous avez montrés de toute façon. Lorsque vous obtenez «erreur 110» en essayant de vous reconnecter à tomcat, cela indique que vous avez une file d'attente de connexions en attente d'être servies qui ne peut plus entrer dans la configuration du backlog d'écoute pour la socket d'écoute dans tomcat.

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.

Si je devais deviner, je soupçonnerais que la grande majorité des requêtes HTTP lorsque le serveur "s'étouffe" est bloquée en attendant que quelque chose revienne de Tomcat. Je parie que si vous tentiez de récupérer du contenu statique directement servi par apache (plutôt que d'être mandaté par tomcat) que cela fonctionnerait même lorsqu'il est normalement «étouffé».

Malheureusement, je ne connais pas tomcat, mais existe-t-il un moyen de manipuler les paramètres de concurrence à la place?

Oh, et vous devrez peut - être envisager la possibilité que ses services réseau externes des thats limitant le nombre de connexions qu'il fait de vous descendre à 300, donc il ne fait aucune différence combien manipulation de la concurrence que vous faites de votre côté avant si pratiquement chaque connexion que vous établissez repose sur une réponse de services Web externes.

Dans l'un de vos commentaires, vous avez mentionné que les données deviennent périmées après 2 minutes. Je suggère de mettre en cache la réponse que vous obtenez de ce service pendant deux minutes pour réduire la quantité de connexions simultanées que vous conduisez vers le service Web externe.

Matthew Ife
la source
2

La première étape pour résoudre ce problème consiste à activer le mod_status d'Apache et à étudier son rapport - jusqu'à ce que vous ayez fait cela, vous marchez aveuglément. Ce n'est pas juste. ;-)

La deuxième chose à mentionner (je déteste moi-même qu'on me réponde aux questions que je ne posais pas, mais ...) est d'utiliser des serveurs frontaux plus efficaces et spéciaux comme nginx.

Aussi, avez - vous exactement restartapache, ou tout simplement gracefully reloaded il? :)

poige
la source
Apache a redémarré .. pas un rechargement gracieux
john titus
@johntitus, eh bien, mod_statusc'est votre ami, de toute façon. :)
poige
1

Pour tout type de déploiement d'entreprise, le MPM pré-fourche est à peu près le pire choix que vous puissiez faire: il engloutit les ressources comme les affaires de personne, et le redémarrage des threads prend FOREVER par rapport aux autres MPM.

Passez au moins au MPM de travail (apache 2.2 et supérieur) ou - mieux encore - passez à la version stable actuelle 2.4.2 avec son événement MPM par défaut .

Les deux géreront facilement des milliers de connexions simultanées avec très peu de frais généraux.

adaptr
la source
merci .. essayé ça aussi .. pas de chance. Les connexions TIME_WAIT continuent d'augmenter. Le serveur cesse de répondre à 350 connexions
John Titus
1
Je ne suis pas d'accord que c'est le pire choix - c'est un mauvais choix pour ce contexte et il est probable que les problèmes seraient atténués en utilisant le serveur threadé, mais une meilleure solution serait d'utiliser un serveur basé sur les événements (nginx ou lighttpd). L'apache basé sur les événements n'est pas assez mature pour être considéré à partir d'un IMHO de déploiement d'entreprise.
symcbean
1

Je sais que c'est une vieille histoire, mais j'ai deux remarques.

Il existe une limite codée en dur pour la directive ServerLimit . http://httpd.apache.org/docs/2.2/mod/mpm_common.html#serverlimit vous verrez que c'est max 20000 / 200K.

Il existe une limite stricte de ServerLimit 20000 compilée dans le serveur (pour la préfork MPM 200000). Ceci est destiné à éviter les effets désagréables causés par les fautes de frappe.

2e Apparemment, nodybo a mentionné que définir ces 2 à un est une très mauvaise idée :

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

cela signifie que vous réutilisez le temps d'attente tôt, devinez quoi? le serveur peut parler au mauvais client sous une forte charge.

J'ai trouvé un très bon article expliquant cela mais - c'est en français ;-) http://vincent.bernat.im/fr/blog/2014-tcp-time-wait-state-linux.html

Nadir
la source
0

extra large avec 34 Go de mémoire.

Le gros fer n'est pas le moyen de faire évoluer les services Web, vous ne faites que déplacer les goulots d'étranglement. Mais même avec autant de mémoire, je soupçonne que 50000 connexions poussent ce que le système est capable de faire si:

Pendant les heures de pointe, le serveur s'étouffe avec environ 300 processus httpd

Il serait utile que vous expliquiez ce que vous entendez par "le serveur s'étouffe".

Il est également très étrange d'avoir une limite aussi élevée pour les connexions mais une limite très basse pour l'hystérésis (serveurs de rechange min / max).

Bien que l'extrait d'erreurs que vous avez fourni ne montre pas le nombre `` trop de fichiers ouverts '', je commencerais par regarder le nombre de descripteurs de fichiers ouverts et les paramètres ulimit.

symcbean
la source
Le serveur s'étouffe car il ne répond même pas aux fichiers html normaux.
John Titus
J'ai changé le maxClients à 3000 maintenant .. toujours le même problème
John Titus
0

Peut-être que l'utilisateur Apache manque de descripteurs de fichiers autorisés? Vous ne les avez pas mentionnés du tout dans votre message. Combien de fichiers gère actuellement Apache est autorisé à avoir?

Janne Pikkarainen
la source
128192 Poignées de fichiers
John Titus
0

Cela ressemble plus à un commentaire, mais comme je ne peux pas, j'ai moins de réputation. Je suis tombé sur un problème exactement similaire à celui de @john titus.

Nous avons rendu le connecteur AJP MaxThreadsproche de notre limite de thread Apache pour résoudre le problème.

Pour surveiller cela, nous avons cherché de l' SYN_SENT aide sur l'état du port netstat avec la commande netstat sur notre port AJP.

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

Cela est descendu à 0, ce qui était toujours un grand nombre avant la limite MaxThread définie sur AJP Connector.

Vineeth
la source