Nous avons une boîte Linux (Ubuntu 12.04) exécutant Nginx (1.5.2), qui agit en tant que proxy inverse/load balancer pour certains hôtes Tornado et Apache. Les serveurs amont sont physiquement et logiquement proches (même centre de données, parfois même rack) et présentent une latence inférieure à la milliseconde entre eux :
PING appserver (10.xx.xx.112) 56(84) bytes of data.
64 octets de appserver (10.xx.xx.112) : icmp_req=1 ttl=64 time=0.180 ms
64 octets de appserver (10.xx.xx.112) : icmp_req=2 ttl=64 time=0.165 ms
64 octets de appserver (10.xx.xx.112) : icmp_req=3 ttl=64 time=0.153 ms
Nous recevons une charge soutenue d'environ 500 requêtes par seconde, et constatons actuellement des pertes de paquets régulières / des pics de latence depuis Internet, même à partir de pings basiques :
sam@AM-KEEN ~> ping -c 1000 loadbalancer
PING 50.xx.xx.16 (50.xx.xx.16): 56 octets de données
64 octets de loadbalancer: icmp_seq=0 ttl=56 time=11.624 ms
64 octets de loadbalancer: icmp_seq=1 ttl=56 time=10.494 ms
... nombreux paquets plus tard ...
Délai de la demande pour icmp_seq 2
64 octets de loadbalancer: icmp_seq=2 ttl=56 time=1536.516 ms
64 octets de loadbalancer: icmp_seq=3 ttl=56 time=536.907 ms
64 octets de loadbalancer: icmp_seq=4 ttl=56 time=9.389 ms
... nombreux paquets plus tard ...
Délai de la demande pour icmp_seq 919
64 octets de loadbalancer: icmp_seq=918 ttl=56 time=2932.571 ms
64 octets de loadbalancer: icmp_seq=919 ttl=56 time=1932.174 ms
64 octets de loadbalancer: icmp_seq=920 ttl=56 time=932.018 ms
64 octets de loadbalancer: icmp_seq=921 ttl=56 time=6.157 ms
--- Statistiques du ping vers 50.xx.xx.16 ---
1000 paquets envoyés, 997 paquets reçus, 0.3% de perte
aller-retour min/moy/max/ecart = 5.119/52.712/2932.571/224.629 ms
Le schéma est toujours le même : les choses fonctionnent bien pendant un certain temps (<20ms), puis un ping disparaît complètement, suivies de trois ou quatre pings à haute latence (>1000ms), puis ça se stabilise à nouveau.
Le trafic arrive via une interface publique liée (nous l'appellerons bond0
) configurée comme suit :
bond0 Encapsulation de lien : Ethernet Adresse matérielle 00:xx:xx:xx:xx:5d
Adresse IP : 50.xx.xx.16 Diffusion : 50.xx.xx.31 Masque : 255.255.255.224
Adresse IPv6 : Portée : Global
Adresse IPv6 : Portée : Lien
UP BROADCAST RUNNING MASTER MULTICAST MTU:1500 Metric:1
Paquets RX : 527181270 erreurs :1 abandonnés :4 dépassements:0 trames :1
Paquets TX : 413335045 erreurs :0 abandonnés :0 dépassements:0 transporteur:0
collisions:0 longueur file d'attente de transmission:0
Octets RX : 240016223540 (240,0 Go) Octets TX : 104301759647 (104,3 Go)
Les requêtes sont ensuite soumises via HTTP aux serveurs amont sur le réseau privé (nous pouvons l'appeler bond1
), qui est configuré comme suit :
bond1 Encapsulation de lien : Ethernet Adresse matérielle 00:xx:xx:xx:xx:5c
Adresse IP : 10.xx.xx.70 Diffusion : 10.xx.xx.127 Masque : 255.255.255.192
Adresse IPv6 : Portée : Lien
UP BROADCAST RUNNING MASTER MULTICAST MTU:1500 Metric:1
Paquets RX : 430293342 erreurs :1 abandonnés :2 dépassements:0 trames :1
Paquets TX : 466983986 erreurs :0 abandonnés :0 dépassements:0 transporteur:0
collisions:0 longueur file d'attente de transmission:0
Octets RX : 77714410892 (77,7 Go) Octets TX : 227349392334 (227,3 Go)
Sortie de uname -a :
Linux 3.5.0-42-generic #65~precise1-Ubuntu SMP Wed Oct 2 20:57:18 UTC 2013 x86_64 GNU/Linux
Nous avons personnalisé sysctl.conf
dans le but de résoudre le problème, sans succès. Sortie de /etc/sysctl.conf
(avec les configurations non pertinentes omises) :
# net: core
net.core.netdev_max_backlog = 10000
# pile ipv4 du réseau
net.ipv4.tcp_ecn = 2
net.ipv4.tcp_sack = 1
net.ipv4.tcp_fack = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_no_metrics_save = 1
net.ipv4.tcp_max_syn_backlog = 10000
net.ipv4.tcp_congestion_control = cubic
net.ipv4.ip_local_port_range = 8000 65535
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_thin_dupack = 1
net.ipv4.tcp_thin_linear_timeouts = 1
net.netfilter.nf_conntrack_max = 99999999
net.netfilter.nf_conntrack_tcp_timeout_established = 300
Sortie de dmesg -d
, avec les messages UFW non-ICMP supprimés :
[508315.349295 < 19.852453>] [UFW BLOCK] IN=bond1 OUT= MAC= SRC=118.xx.xx.143 DST=50.xx.xx.16 LEN=68 TOS=0x00 PREC=0x00 TTL=51 ID=43221 PROTO=ICMP TYPE=3 CODE=1 [SRC=50.xx.xx.16 DST=118.xx.xx.143 LEN=40 TOS=0x00 PREC=0x00 TTL=249 ID=10220 DF PROTO=TCP SPT=80 DPT=53817 WINDOW=8190 RES=0x00 ACK FIN URGP=0 ]
[517787.732242 < 0.443127>] Peer 190.xx.xx.131:59705/80 unexpectedly shrunk window 1155488866:1155489425 (repaired)
Comment puis-je diagnostiquer la cause de ce problème sur une boîte Linux de la famille Debian ?