limite de connexion nginx

Nous avons eu 2 serveurs nginx fonctionnant parfaitement à 1000 points / seconde au total devant 3 serveurs php5-fpm avec des connexions TCP. Nous pensions qu’un seul serveur nginx serait suffisant et que nous lui redirections tout notre trafic. Mais, le serveur ne pouvait pas servir plus de 750 fois / s. Il a Gigabit Ethernet et le trafic total ne dépasse pas 100 Mbits (Debian 6.0)

Nous n’avons pu trouver aucune raison et après googling a découvert qu’il pourrait être lié aux problèmes de TCP. Mais il ne semblait pas très probable que nous fassions un changement avec ce nombre de connexions et de bande passante (environ 70 Mbits / sec).

Nous avons examiné l’erreur nginx et les journaux d’access. Existe-t-il un outil ou un fichier qui pourrait nous aider à trouver la solution au problème?

La plupart des dissortingbutions Linux ont 28232 ports éphémères disponibles . Un serveur a besoin d’un port éphémère pour chaque connexion afin de libérer le port principal (c’est-à-dire le port du serveur HTTP 80) pour les nouvelles connexions.

Ainsi, il semblerait que si le serveur gère 1000 requêtes / sec pour le contenu généré par php5-fpm sur TCP, vous allouez 2000 ports / sec. Ce n’est pas vraiment le cas, il est probable que 5% de PHP et 95% de statique (pas d’allocation de port) et IIRC nginx <-> php-fpm garde les ports ouverts pour les requêtes suivantes. Il y a beaucoup de facteurs qui peuvent affecter ces nombres, mais pour les arguments, disons 1000 allocations de ports / sec.

En apparence, cela ne semble pas être un problème, mais par défaut, les ports ne sont pas immédiatement libérés et mis à disposition pour de nouvelles connexions. Il y a plusieurs raisons à ce comportement et je recommande fortement une compréhension approfondie du protocole TCP avant de procéder à des modifications arbitraires détaillées ici (ou ailleurs).

Principalement, un état de connexion appelé TIME_WAIT (socket attend après la fermeture pour gérer les paquets encore présents sur le réseau, page de manuel netstat ) est ce qui empêche les ports d’être libérés pour être réutilisés. Sur les kernelx linux récents (tous?), TIME_WAIT est codé en dur à 60 secondes et, conformément à la RFC793, une connexion peut restr dans TIME_WAIT jusqu’à quatre minutes!

Cela signifie qu’au moins 1000 ports seront utilisés pendant au moins 60 secondes . Dans le monde réel, vous devez prendre en compte le temps de transit, les requêtes persistantes (plusieurs demandes utilisent la même connexion) et les ports de service (entre nginx et le serveur principal). Permet de l’abaisser arbitrairement à 750 ports / s.

En ~ 37 secondes, tous vos ports disponibles seront épuisés (28232/750 = 37). C’est un problème, car il faut 60 secondes pour libérer un port!

Pour voir tous les ports utilisés, lancez apache bench ou quelque chose de similaire qui peut générer le nombre de requêtes par seconde que vous accordez. Puis lancez:

 root:~# netstat -n -t -o | grep timewait 

Vous obtiendrez une sortie comme (mais beaucoup, beaucoup plus de lignes):

 tcp 0 0 127.0.0.1:40649 127.1.0.2:80 TIME_WAIT timewait (57.58/0/0) tcp 0 0 127.1.0.1:9000 127.0.0.1:50153 TIME_WAIT timewait (57.37/0/0) tcp 0 0 127.0.0.1:40666 127.1.0.2:80 TIME_WAIT timewait (57.69/0/0) tcp 0 0 127.0.0.1:40650 127.1.0.2:80 TIME_WAIT timewait (57.58/0/0) tcp 0 0 127.0.0.1:40662 127.1.0.2:80 TIME_WAIT timewait (57.69/0/0) tcp 0 0 127.0.0.1:40663 127.1.0.2:80 TIME_WAIT timewait (57.69/0/0) tcp 0 0 127.0.0.1:40661 127.1.0.2:80 TIME_WAIT timewait (57.61/0/0) 

Pour un total cumulé de ports alloués:

 root:~# netstat -n -t -o | wc -l 

Si vous recevez des demandes ayant échoué, le nombre sera de / proche de 28232.

Comment résoudre le problème?

  1. Augmentez le nombre de ports éphémères de 28232 à 63976.

     sysctl -w net.ipv4.ip_local_port_range="1024 65000" 
  2. Autoriser linux à réutiliser les ports TIME_WAIT avant l’expiration du délai.

     sysctl -w net.ipv4.tcp_tw_reuse="1" 
  3. Adresses IP supplémentaires.