Bonjour,
je rencontre un problème d'établissement de connexions TCP sur un serveur
par forte charge, qui se concrétise par des
timeouts de connexion. Ce serveur établit de nombreuses connexions :
- serveur web NGiNX
- fichiers statiques sur NFSv4 (4 connexions TCP)
- reverse-proxy sur une 20ène de serveurs web Apache2/PHP, via l'IP publique
- reverse-proxy sur un cluster XMPP
Evidemment il y a quelques axes d'améliorations simple : passer par le
réseau privé pour limiter les connexions sur
l'interface réseau publique, ... mais ce n'est pas le but de ce mail.
Sous forte charge, parfois une simple connexion TCP a des difficultés pour
s'établir. Pour tester, j'écarte des soucis
potentiels avec NGiNX et lance un serveur netcat sur le port 8080 :
nc -l -k 8080
et depuis un poste client sous Linux :
while true; do date -R | tee -a /dev/stderr | nc -w 2 perceval.local 8080
|| echo ERR; sleep 0.2; done
Lorsque le problème survient, des "ERR" s'affichent.
A ce moment, j'ai tenté plusieurs choses pour tenter de trouver la source
de ces problèmes de connexions, et aucun ne
s'est avéré "payant" :
- désactiver le firewall
- supprimer et décharger conntrack
- changer l'algorythme de congestion TCP de cubic à autre chose
- mesurer le nombre de connexions TCP établit ou en FIN_WAIT : à 10k total
le soucis peut très bien se produire ou pas
- modifier plusieurs paramètre de config TCP / Kernel :
net.ipv4.tcp_sack = 1
net.ipv4.tcp_fack = 1
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_syncookies = 0
net.ipv4.tcp_low_latency = 0
net.core.netdev_max_backlog = 4000
net.ipv4.ip_local_port_range = 1024 65000
net.ipv4.tcp_max_syn_backlog = 163840
net.ipv4.tcp_synack_retries = 1
net.ipv4.tcp_fin_timeout = 10
net.ipv4.tcp_no_metrics_save = 1
net.ipv4.tcp_max_tw_buckets = 400000
net.core.somaxconn = 8192
fs.file-max = 1310720
net.ipv4.tcp_tw_recycle=1
net.ipv4.tcp_tw_reuse=1
En vain. Sauf un paramètre qui débloque tout quand il est désactivé :
net.ipv4.tcp_timestamps=0
C'est très net, si je désactive les timestamps TCP coté serveur (ou coté
client forcément), je n'ai plus aucun problème
d'établissement de connexions TCP.
A ce moment commence les recherches sur Google, et tout ce que je trouve
est ambigu : il vaut mieux activer les
timestamps TCP pour des raisons de performances, mais il faut mieux les
désactiver pour des problèmes de sécurité.
Activé, l'attaquant peut récupérer l'uptime du serveur... Franchement osef
nan ?
Ce qui me gène plus, c'est qu'il est conseillé d'activer ce paramètre en
cas de soucis de congestion TCP...
Peut-être qu'avec la quantité de trafic, le kernel n'est pas capable de
fournir assez de timestamps ? Peut-être que la
fréquence du timer Linux a une incidence ?
Le kernel utilisé est le 3.5.5 avec les patchs Google d'activé (RPS, RFS)
et cette config de timer :
CONFIG_NO_HZ=y
CONFIG_HZ_250=y
CONFIG_HZ=250
J'essaye avec 1000 HZ : aucune incidence.
La désactivation de ce paramètre net.ipv4.tcp_timestamps ne doit pas agir
que sur les timestamps, peut-être que les
algos de congestion TCP, ou certains modules, ou une partie de la stack
TCP, utilisent les timestamps TCP, et peut-être
que c'est un de ces modules qui pose problème ?
Avez vous déjà expérimenté ce type de soucis ?
Je suis dispo pour faire des tests si vous avez des idées !!
--
Greg