Qu'est-ce qui limite le nombre maximal de connexions sur un serveur Linux?

90

Quel paramètre de noyau ou autres paramètres contrôlent le nombre maximal de sockets TCP pouvant être ouverts sur un serveur Linux? Quels sont les compromis de permettre plus de connexions?

J'ai remarqué en charge de tester un serveur Apache avec ab qu'il est assez facile à emboiter les connexions ouvertes sur le serveur. Si vous laissez l'option -k de ab, qui permet la réutilisation de la connexion et que celui-ci envoie plus de 10 000 demandes environ, Apache traite les 11 000 premières demandes environ, puis s'arrête pendant 60 secondes. Un aperçu de la sortie netstat montre 11 000 connexions dans l'état TIME_WAIT. Apparemment, c'est normal. Les connexions sont maintenues ouvertes par défaut pendant 60 secondes même après que le client en a terminé avec elles pour des raisons de fiabilité TCP .

Il semble que ce serait un moyen facile de créer un serveur et je me demande quels sont les réglages et les précautions habituels.

Voici ma sortie de test:

# ab -c 5 -n 50000 http://localhost/
This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 5000 requests
Completed 10000 requests
apr_poll: The timeout specified has expired (70007)
Total of 11655 requests completed

Voici la commande netstat que j'ai exécutée pendant le test:

 # netstat --inet -p | grep "localhost:www" | sed -e 's/ \+/ /g' | cut -d' ' -f 1-4,6-7 | sort | uniq -c 
  11651 tcp 0 0 localhost:www TIME_WAIT -
      1 tcp 0 1 localhost:44423 SYN_SENT 7831/ab
      1 tcp 0 1 localhost:44424 SYN_SENT 7831/ab
      1 tcp 0 1 localhost:44425 SYN_SENT 7831/ab
      1 tcp 0 1 localhost:44426 SYN_SENT 7831/ab
      1 tcp 0 1 localhost:44428 SYN_SENT 7831/ab
Ben Williams
la source

Réponses:

64

J'ai finalement trouvé le réglage qui limitait vraiment le nombre de connexions: net.ipv4.netfilter.ip_conntrack_max. Ce paramètre a été défini sur 11 776 et le nombre de demandes que je peux répondre à mon test est le nombre de requêtes que je peux traiter avant d'attendre tcp_fin_timeoutquelques secondes que de nouvelles connexions deviennent disponibles. La conntracktable correspond à ce que le noyau utilise pour suivre l’état des connexions. Ainsi, une fois qu’elle est pleine, le noyau commence à déposer des paquets et à l’afficher dans le journal:

Jun  2 20:39:14 XXXX-XXX kernel: ip_conntrack: table full, dropping packet.

L'étape suivante consistait à faire en sorte que le noyau recycle toutes ces connexions dans l' TIME_WAITétat plutôt que de supprimer des paquets. Je pourrais le faire en allumant tcp_tw_recycleou en augmentant ip_conntrack_maxpour être plus grand que le nombre de ports locaux mis à disposition pour les connexions ip_local_port_range. Je suppose qu'une fois que le noyau est sorti des ports locaux, il commence à recycler les connexions. Cela utilise plus de connexions de suivi de la mémoire, mais il semble que la meilleure solution que d'activer, étant tcp_tw_recycledonné que la documentation implique que c'est dangereux.

Avec cette configuration, je peux exécuter un ab toute la journée et ne jamais manquer de connexions:

net.ipv4.netfilter.ip_conntrack_max = 32768
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_tw_reuse = 0
net.ipv4.tcp_orphan_retries = 1
net.ipv4.tcp_fin_timeout = 25
net.ipv4.tcp_max_orphans = 8192
net.ipv4.ip_local_port_range = 32768    61000

Le tcp_max_orphansréglage n'a eu aucun effet sur mes tests et je ne sais pas pourquoi. Je penserais que cela fermerait les connexions dans l' TIME_WAITétat une fois qu'il y en aurait 8192 mais cela ne me convient pas.

Ben Williams
la source
3
Où configurons-nous ces paramètres?
Codevalley
2
@Codevalley Cela peut être le système dépendant , mais sur Ubuntu Server , ils vont dans /etc/sysctl.conf
Ben Williams
24

Vous voulez vraiment regarder ce que le système de fichiers / proc a à vous offrir à cet égard.

Sur cette dernière page, les éléments suivants pourraient vous intéresser:

  • / proc / sys / net / ipv4 / tcp_max_orphans , qui contrôle le nombre maximal de sockets détenues par le système non attachées à quelque chose. Augmenter cette quantité peut prendre jusqu'à 64 Ko de mémoire non permutable par socket orphelin .
  • / proc / sys / net / ipv4 / tcp_orphan_retries , qui contrôle le nombre de tentatives avant qu'un socket soit orphelin et fermé. Il y a une note spécifique sur cette page à propos des serveurs Web qui vous intéresse directement ...
Avery Payne
la source
tcp_max_orphans est intéressant, mais il semble que cela ne fonctionne pas. Lorsque j'essaie de mesurer les sockets orphelins au cours de mon test, j'en vois 11 651 tandis que tcp_max_orphans vaut 8 092. # netstat --inet -p | grep "localhost: www" | sed -e 's / \ + / / g' | cut -d '' -f 1-4,6-7 | trier | uniq -c 11651 tcp 0 0 localhost: www TIME_WAIT -
Ben Williams
Regardez le paramètre tcp_orphan_retries - l'idée étant, les sockets sont "cueillies" plus rapidement ...
Avery Payne
La suggestion de @Jauder Ho + tcp_orphan_retries semble être une victoire potentielle pour votre situation.
Avery Payne
3

Je ne pense pas qu'il soit possible de régler cela directement. Cela entre dans la catégorie du réglage TCP / IP. Pour savoir ce que vous pouvez accorder, essayez «man 7 tcp». Le sysctl ('man 8 sysctl') est utilisé pour les définir. 'sysctl -a | grep tcp 'va vous montrer la plupart de ce que vous pouvez accorder, mais je ne suis pas sûr que cela les montre toutes. De plus, à moins que cela ne change, les sockets TCP / IP ouverts ressemblent à des descripteurs de fichier. Donc, ceci et la prochaine section de ce lien pourraient être ce que vous recherchez.

Kyle Brandt
la source
2

Essayez également de définir tcp_fin_timeout. Cela devrait fermer TIME_WAIT plus rapidement.

net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
Jauder Ho
la source
Attention ici! Expérimenté à la dure. "Cela peut provoquer des chutes de trames avec équilibrage de charge et NAT, utilisez-le uniquement pour un serveur qui communique uniquement via votre réseau local." - wiki.archlinux.org/index.php/Sysctl
Henk
@ Henk Je suppose tcp_tw_recycleque c'est potentiellement dangereux. tcp_tw_reuseest plus sûr et je ne vois aucune raison de les utiliser simultanément.
Vladislav Rastrusny
2

Le stock apache (1) était auparavant prédéfini pour ne prendre en charge que 250 connexions simultanées. Si vous en vouliez plus, il y avait un fichier d'en-tête à modifier pour autoriser plusieurs sessions simultanées. Je ne sais pas si cela est toujours vrai avec Apache 2.

En outre, vous devez ajouter une option permettant d'autoriser le chargement de davantage de descripteurs de fichiers ouverts pour le compte qui exécute Apache, ce que les commentaires précédents ne peuvent pas signaler.

Faites attention aux paramètres de votre opérateur et aux types de délais keepalive que vous avez dans Apache lui-même, au nombre de serveurs de secours en cours d'exécution à la fois et à la vitesse à laquelle ces processus supplémentaires sont supprimés.

rasjani
la source
1

Vous pouvez réduire le temps passé dans l'état TIME_WAIT (Définissez net.ipv4.tcp_fin_timeout). Vous pouvez remplacer Apache par YAWS ou nginx ou quelque chose de similaire.

Les échanges de davantage de connexions impliquent généralement une utilisation de la mémoire et, si vous avez un processus de forking, de nombreux processus enfants surchargent votre processeur.

Devdas
la source
1
tcp_fin_timeout ne sert pas à définir l’expiration de TIME-WAIT, qui ne peut pas être changée en dehors de la reconstruction du noyau, mais à FIN, comme son nom l’indique.
Alexandr Kurilin
0

Le nombre absolu de sockets pouvant être ouverts sur une seule adresse IP est de 2 ^ 16 et est défini par TCP / UDP, et non par le noyau.

Jason Tan
la source
6
Non ce n'est pas. Vous pouvez en ouvrir davantage, car le port local n'a pas besoin d'être unique tant que les adresses distantes sont différentes. De plus, l'OP dit par serveur, et vous pouvez avoir> 1 adresse par serveur.
MarkR