У нас есть Linux (Ubuntu 12.04) с Nginx (1.5.2), который действует как обратный прокси / балансировщик нагрузки для некоторых хостов Tornado и Apache. Вышестоящие серверы физически и логически близки (один и тот же контроллер домена, иногда одна стойка) и между ними наблюдается задержка менее миллисекунды:
PING appserver (10.xx.xx.112) 56(84) bytes of data.
64 bytes from appserver (10.xx.xx.112): icmp_req=1 ttl=64 time=0.180 ms
64 bytes from appserver (10.xx.xx.112): icmp_req=2 ttl=64 time=0.165 ms
64 bytes from appserver (10.xx.xx.112): icmp_req=3 ttl=64 time=0.153 ms
Мы получаем устойчивую нагрузку около 500 запросов в секунду, и в настоящее время наблюдаются регулярные всплески потери пакетов / задержки из Интернета, даже при базовом пинге:
sam@AM-KEEN ~> ping -c 1000 loadbalancer
PING 50.xx.xx.16 (50.xx.xx.16): 56 data bytes
64 bytes from loadbalancer: icmp_seq=0 ttl=56 time=11.624 ms
64 bytes from loadbalancer: icmp_seq=1 ttl=56 time=10.494 ms
... many packets later ...
Request timeout for icmp_seq 2
64 bytes from loadbalancer: icmp_seq=2 ttl=56 time=1536.516 ms
64 bytes from loadbalancer: icmp_seq=3 ttl=56 time=536.907 ms
64 bytes from loadbalancer: icmp_seq=4 ttl=56 time=9.389 ms
... many packets later ...
Request timeout for icmp_seq 919
64 bytes from loadbalancer: icmp_seq=918 ttl=56 time=2932.571 ms
64 bytes from loadbalancer: icmp_seq=919 ttl=56 time=1932.174 ms
64 bytes from loadbalancer: icmp_seq=920 ttl=56 time=932.018 ms
64 bytes from loadbalancer: icmp_seq=921 ttl=56 time=6.157 ms
--- 50.xx.xx.16 ping statistics ---
1000 packets transmitted, 997 packets received, 0.3% packet loss
round-trip min/avg/max/stddev = 5.119/52.712/2932.571/224.629 ms
Шаблон всегда один и тот же: какое-то время все работает нормально (<20 мс), затем пинг полностью падает, затем три или четыре пинга с высокой задержкой (> 1000 мс), затем снова стабилизируется.
Трафик поступает через связанный публичный интерфейс (назовем его bond0
) настроен как таковой:
bond0 Link encap:Ethernet HWaddr 00:xx:xx:xx:xx:5d
inet addr:50.xx.xx.16 Bcast:50.xx.xx.31 Mask:255.255.255.224
inet6 addr: <ipv6 address> Scope:Global
inet6 addr: <ipv6 address> Scope:Link
UP BROADCAST RUNNING MASTER MULTICAST MTU:1500 Metric:1
RX packets:527181270 errors:1 dropped:4 overruns:0 frame:1
TX packets:413335045 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:240016223540 (240.0 GB) TX bytes:104301759647 (104.3 GB)
Затем запросы отправляются через HTTP на вышестоящие серверы в частной сети (мы можем назвать это bond1
), который настроен так:
bond1 Link encap:Ethernet HWaddr 00:xx:xx:xx:xx:5c
inet addr:10.xx.xx.70 Bcast:10.xx.xx.127 Mask:255.255.255.192
inet6 addr: <ipv6 address> Scope:Link
UP BROADCAST RUNNING MASTER MULTICAST MTU:1500 Metric:1
RX packets:430293342 errors:1 dropped:2 overruns:0 frame:1
TX packets:466983986 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:77714410892 (77.7 GB) TX bytes:227349392334 (227.3 GB)
Вывод uname -a:
Linux <hostname> 3.5.0-42-generic #65~precise1-Ubuntu SMP Wed Oct 2 20:57:18 UTC 2013 x86_64 GNU/Linux
Мы настроили sysctl.conf
в попытке исправить проблему, но безуспешно. Выход /etc/sysctl.conf
(с опущенными нерелевантными конфигами):
# net: core
net.core.netdev_max_backlog = 10000
# net: ipv4 stack
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
Выход dmesg -d
, с подавленными не-ICMP сообщениями UFW:
[508315.349295 < 19.852453>] [UFW BLOCK] IN=bond1 OUT= MAC=<mac addresses> 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)
Как я могу определить причину этой проблемы в системе Linux семейства Debian?
Если какая-либо часть вашей сети по пути перегружена, или если какой-либо канал в сети выдает ошибки, вы можете столкнуться с потерей пакетов. Это не будет отображаться в счетчике ошибок интерфейса, если только у вас не возникнет проблема прямо при кабельном соединении коммутатора с сервером. Если проблема в другом месте сети, это отображается как потерянные пакеты.
Вы можете обнаружить эту проблему, если у вас есть TCP-трафик, поскольку в ядре есть счетчики, которые отслеживают, как TCP выполняет шаги восстановления для учета потерянных пакетов в потоке. Взгляните на -s
(статистика) опция на netstat
. Представленные значения являются счетчиками, поэтому вам нужно некоторое время понаблюдать за ними, чтобы понять, что нормально, а что аномально, но данные есть. В retransmit
и data loss
счетчики особенно полезны.
[sadadmin@busted ~]$ netstat -s | egrep -i 'loss|retran'
2058 segments retransmited
526 times recovered from packet loss due to SACK data
193 TCP data loss events
TCPLostRetransmit: 7
2 timeouts after reno fast retransmit
1 timeouts in loss state
731 fast retransmits
18 forward retransmits
97 retransmits in slow start
4 sack retransmits failed
Некоторые инструменты отбирают эти значения и изменяют их для вас, чтобы вы могли легко увидеть, когда что-то пошло не так. я использую Мунин.