Je suis en train de programmer un serveur et il semble que mon nombre de connexions est limité car ma bande passante n'est pas saturée, même lorsque j'ai défini le nombre de connexions sur "illimité".
Comment puis-je augmenter ou éliminer un nombre maximal de connexions que ma machine Ubuntu Linux peut ouvrir à la fois? Est-ce que le système d'exploitation limite cela ou est-ce le routeur ou le FAI? Ou s'agit-il d'autre chose?
Certaines limites, tant du côté client que du côté serveur, ont un impact sur le nombre maximal de connexions, bien que ce soit un peu différemment.
Du côté client: Augmentez la plage de ports éphermaux et diminuez le tcp_fin_timeout
Pour connaître les valeurs par défaut:
sysctl net.ipv4.ip_local_port_range
sysctl net.ipv4.tcp_fin_timeout
La plage de ports éphermiques définit le nombre maximal de sockets sortants qu'un hôte peut créer à partir d'un I.P. donné. adresse. Le fin_timeout
définit le temps minimum pendant lequel ces sockets resteront dans l'état TIME_WAIT
(inutilisable après avoir été utilisé une fois). Les paramètres par défaut du système sont:
net.ipv4.ip_local_port_range = 32768 61000
net.ipv4.tcp_fin_timeout = 60
En gros, cela signifie que votre système ne peut pas toujours garantir plus de (61000 - 32768) / 60 = 470
sockets par seconde. Si cela ne vous convient pas, vous pouvez commencer par augmenter le port_range
. La définition de la plage sur 15000 61000
est assez courante de nos jours. Vous pouvez augmenter encore la disponibilité en diminuant le fin_timeout
. Supposons que vous fassiez les deux, vous devriez voir plus de 1 500 connexions sortantes par seconde, plus facilement.
Pour modifier les valeurs :
sysctl net.ipv4.ip_local_port_range="15000 61000"
sysctl net.ipv4.tcp_fin_timeout=30
Ce qui précède ne doit pas être interprété comme un facteur ayant une incidence sur la capacité du système à établir des connexions sortantes par seconde. Mais ces facteurs affectent plutôt la capacité du système à gérer les connexions simultanées de manière durable pendant de longues périodes "d'activité".
Les valeurs Sysctl par défaut sur une machine Linux typique pour tcp_tw_recycle
& tcp_tw_reuse
seraient
net.ipv4.tcp_tw_recycle=0
net.ipv4.tcp_tw_reuse=0
Celles-ci ne permettent pas une connexion depuis une socket "utilisée" (en attente) et forcent les sockets à durer le cycle complet time_wait
. Je recommande le réglage:
sysctl net.ipv4.tcp_tw_recycle=1
sysctl net.ipv4.tcp_tw_reuse=1
Cela permet de cycler rapidement les sockets dans l'état time_wait
et de les réutiliser. Mais avant de procéder à cette modification, assurez-vous que cela n’entre pas en conflit avec les protocoles que vous utiliseriez pour l’application qui a besoin de ces sockets. Assurez-vous de lire le message "Composer avec TCP TIME-WAIT" de Vincent Bernat pour comprendre les implications. L'option net.ipv4.tcp_tw_recycle
est assez problématique pour les serveurs faisant face au public, car elle ne gère pas les connexions de deux ordinateurs différents derrière le même périphérique NAT , qui est un problème difficile à détecter et à attendre pour vous mordre. Notez que net.ipv4.tcp_tw_recycle
a été supprimé de Linux4.12.
Côté serveur: La valeur net.core.somaxconn
a un rôle important. Il limite le nombre maximal de demandes en file d'attente à un socket d'écoute. Si vous êtes sûr de la capacité de votre application serveur, augmentez-la de 128 par défaut à 128 à 1024. Vous pouvez maintenant tirer parti de cette augmentation en modifiant la variable backlog d'écoute dans l'appel d'écoute de votre application, en un entier égal ou supérieur.
sysctl net.core.somaxconn=1024
Les paramètres txqueuelen
de vos cartes Ethernet ont également un rôle à jouer. Les valeurs par défaut sont 1000, alors augmentez-les jusqu'à 5000, voire davantage si votre système peut le gérer.
ifconfig eth0 txqueuelen 5000
echo "/sbin/ifconfig eth0 txqueuelen 5000" >> /etc/rc.local
De même, bump up les valeurs pour net.core.netdev_max_backlog
et net.ipv4.tcp_max_syn_backlog
. Leurs valeurs par défaut sont 1000 et 1024 respectivement.
sysctl net.core.netdev_max_backlog=2000
sysctl net.ipv4.tcp_max_syn_backlog=2048
Pensez maintenant à démarrer vos applications côté client et serveur en augmentant le nombre de FD dans le shell.
Outre la technique ci-dessus, une autre technique couramment utilisée par les programmeurs consiste à réduire le nombre d'appels tcp write. Ma propre préférence est d'utiliser un tampon dans lequel je pousse les données que je souhaite envoyer au client, puis aux points appropriés, j'écris les données mises en mémoire tampon dans le socket actuel. Cette technique me permet d’utiliser des paquets de données volumineux, de réduire la fragmentation et d’utiliser mon processeur aussi bien au niveau de l’utilisateur qu’au niveau du noyau.
Deux variables permettent de définir le nombre maximal de connexions. Très probablement, vous commencez par manquer de numéros de fichiers. Vérifiez ulimit -n. Après cela, il y a des paramètres dans/proc, mais ceux par défaut sont des dizaines de milliers.
Plus important encore, on dirait que vous faites quelque chose de mal. Une seule connexion TCP devrait pouvoir utiliser toute la bande passante entre deux parties; si ce n'est pas le cas:
ping -s 1472
...)tc
iperf
J'ai peut-être mal compris. Peut-être que vous faites quelque chose comme Bittorrent, où vous avez besoin de beaucoup de connexions. Si tel est le cas, vous devez déterminer le nombre de connexions que vous utilisez réellement (essayez netstat
ou lsof
). Si ce nombre est important, vous pourriez:
ulimit -n
. Malgré tout, environ 1 000 connexions (par défaut sur mon système) en représentent quelques-unes.iostat -x
?De même, si vous utilisez un routeur NAT de grande qualité (Linksys, Netgear, DLink, etc.), prenez garde de dépasser ses capacités avec des milliers de connexions.
J'espère que cela fournit de l'aide. Vous posez vraiment une question de mise en réseau.
Pour améliorer la réponse donnée par derobert,
Vous pouvez déterminer votre limite de connexion au système d'exploitation en accédant à nf_conntrack_max.
Par exemple: cat/proc/sys/net/netfilter/nf_conntrack_max
Vous pouvez utiliser le script suivant pour compter le nombre de connexions TCP à une plage donnée de ports TCP. Par défaut 1-65535.
Cela confirmera si vous atteignez ou non votre limite de connexion au système d'exploitation.
Voici le script.
#!/bin/bash
OS=$(uname)
case "$OS" in
'SunOS')
AWK=/usr/bin/nawk
;;
'Linux')
AWK=/bin/awk
;;
'AIX')
AWK=/usr/bin/awk
;;
esac
netstat -an | $AWK -v start=1 -v end=65535 ' $NF ~ /TIME_WAIT|ESTABLISHED/ && $4 !~ /127\.0\.0\.1/ {
if ($1 ~ /\./)
{sip=$1}
else {sip=$4}
if ( sip ~ /:/ )
{d=2}
else {d=5}
split( sip, a, /:|\./ )
if ( a[d] >= start && a[d] <= end ) {
++connections;
}
}
END {print connections}'
Au niveau de l'application, voici ce que peut faire un développeur:
Du côté du serveur:
Vérifiez si l'équilibreur de charge (le cas échéant) fonctionne correctement.
Transformez lentement le délai d'attente TCP en réponse rapide 503; si le chargement de l'équilibreur fonctionne correctement, il doit sélectionner la ressource de travail à servir et il vaut mieux que de rester avec des massages d'erreur inattendus.
Exemple: si vous utilisez un serveur de nœud, vous pouvez utiliser toobusy à partir de npm. Mise en œuvre quelque chose comme:
var toobusy = require('toobusy');
app.use(function(req, res, next) {
if (toobusy()) res.send(503, "I'm busy right now, sorry.");
else next();
});
Pourquoi 503? Voici quelques bonnes idées contre la surcharge: http://ferd.ca/queues-don-t-fix-overload.html
Nous pouvons également travailler du côté client:
Essayez de grouper les appels par lots, réduisez le trafic et le nombre total de demandes client n/b et serveur.
Essayez de créer une couche intermédiaire de cache pour gérer les demandes de doublons inutiles.