У меня есть приложение, в котором клиент подключается к серверу через простой протокол на основе TCP через TLS / SSL. В процессе разработки это отлично работало в течение многих месяцев, пока мы создавали наше приложение. Недавно, когда мы готовились к запуску, я добавил в микс HAProxy, чтобы упростить некоторый порядок распределения нагрузки. Технически все работает, но проблема в том, что теперь клиент видит совершенно случайные тайм-ауты. Обычно они непостоянны, но длится примерно 60 секунд. Иногда это может произойти через 25 секунд. Сервер, который haproxy перенаправляет TCP-соединение на уведомления и выполняет чистое отключение, проблема в том, что вы не хотите, чтобы куча одновременных подключений прерывалась и повторно подключалась снова и снова без какой-либо причины. Это влияет не только на другие вещи, но и на нашу инфраструктуру публикации / подписки. Клиент достаточно умен, чтобы сразу же переподключиться, но это не то поведение, которого мы желаем. Сервер, ответственный за прием этих TCP-соединений через SSL, не требует поддержки активности. Я собираюсь пойти дальше и предположить, что есть какое-то неявное значение, которое я не вижу в моей конфигурации HAProxy, вызывающее эти случайные тайм-ауты или что-то, что требует сохранения активности TCP. Однако тот факт, что таймауты не всегда совпадают, заставляет меня задуматься об обратном. Если бы это было 60 секунд каждый раз, я бы убедился, что это проблема конфигурации. В данном конкретном случае это не всегда 60 секунд. Вот как сейчас выглядит моя конфигурация:
global
stats socket /home/haproxy/status user haproxy group haproxy
log 127.0.0.1 local1 info
# log 127.0.0.1 local5 info
maxconn 4096
ulimit-n 8250
# typically: /home/haproxy
chroot /home/haproxy
user haproxy
group haproxy
daemon
quiet
pidfile /home/haproxy/haproxy.pid
defaults
log global
mode http
option httplog
option dontlognull
retries 3
option redispatch
maxconn 2000
contimeout 5000
clitimeout 60000
srvtimeout 60000
# Configuration for one application:
# Example: listen myapp 0.0.0.0:80
listen www 0.0.0.0:443
mode tcp
balance leastconn
# Example server line (with optional cookie and check included)
# server srv3.0 10.253.43.224:8000 srv03.0 check inter 2000 rise 2 fall 3
# Status port (by default, localhost only...for debugging purposes)
server ANID3 10.0.1.2:8888 check inter 3000 rise 2 fall 3 maxconn 500
server ANID1 10.0.1.3:8888 check inter 3000 rise 2 fall 3 maxconn 500
server ANID2 10.0.1.4:8888 check inter 3000 rise 2 fall 3 maxconn 500
listen health 0.0.0.0:9999
mode http
balance roundrobin
stats uri /haproxy-status
Я убедился, что проблема HAProxy заключается в том, что наш клиент обходит его и переходит непосредственно к одному серверу приложений, где нет тайм-аутов, и все хорошо и красиво. Как только я маршрутизирую его через один из двух наших серверов haproxy, случаются случайные отключения в диапазоне от 25 до 60 секунд.
Спасибо, что взглянули на это. Это довольно неприятно, но я уверен, что это непонимание того, что именно HAProxy ожидает от моего клиента.
Не должно быть причин для досрочного закрытия связи, я даже не понимаю, как это может произойти. Ваши таймауты установлены на 60 секунд, поэтому они должны быть 60 секунд.
Хммм, подожди, разве ты не бежишь? haproxy внутри виртуальной машины с быстрыми часами? Это проблема некоторых виртуальных машин, где часы иногда работают слишком быстро (более чем в два раза больше правильной скорости) или вместо этого слишком медленно с большими скачками один раз в минуту. Haproxy знает, как защищаться от слишком длинных пауз и временных скачков, которые он может обнаружить, но, очевидно, он не может защитить от слишком быстрого бега часов без уведомления системы.
Если вы находитесь на виртуальной машине, вы можете попробовать следующее:
$ while sleep 1; do date; done
И пусть это продлится одну или две минуты. Убедитесь сами, работает ли он с правильной скоростью. Прошло много времени с тех пор, как я в последний раз наблюдал эту неприятную проблему, но это не значит, что она больше не повторится.
Кстати, вы должны установить "option tcplog
"в разделе TCP и проверьте журналы. Затем вы увидите, было ли это с точки зрения haproxy тайм-аутом, прерыванием работы клиента или сервера и через какое время.
попробуйте это, я исправил эту проблему.
listen mysql-slaves
bind 0.0.0.0:3306
mode tcp
maxconn 20000
option mysql-check user haproxy
balance roundrobin
contimeout 5000
clitimeout 50000
srvtimeout 50000
....
Можете ли вы проверить это:
defaults
timeout client 60000
option http-server-close
Вместо clitimeout
https://code.google.com/p/haproxy-docs/wiki/http_server_close
Поскольку время варьируется, и вы окончательно подтвердили, что серверная часть не несет ответственности, вряд ли это будет настройка тайм-аута.
Что, как ни странно, привело бы меня к решению, которое, возможно, является перезапуском службы.
Если что-то перезапускает HAProxy на cron (например, monit - который будет опрашивать каждые 60 секунд), это может означать, что сеанс длится до 60 секунд до завершения или короче.
Дважды проверьте время безотказной работы на HAProxy, и если оно всегда меньше минуты или около того - вот вам ответ.
Кроме того, возможно, стоит просмотреть статистику HAProxy, чтобы убедиться, что вы не достигли каких-либо жестких ограничений сеанса, вызывающих срабатывание альтернативного тайм-аута. Если меньше чем maxqueue
запросы уже в очереди, для timeout queue
секунд, если после этого тайм-аута ненасыщенный сервер не будет найден, запрос будет отброшен.