Назад | Перейти на главную страницу

Нужна помощь в устранении неполадок, связанных с прерыванием тайм-аута TCP в HAProxy

У меня есть приложение, в котором клиент подключается к серверу через простой протокол на основе 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 знает, как защищаться от слишком длинных пауз и временных скачков, которые он может обнаружить, но, очевидно, он не может защитить от слишком быстрого бега часов без уведомления системы.

Если вы находитесь на виртуальной машине, вы можете попробовать следующее:

$  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 секунд, если после этого тайм-аута ненасыщенный сервер не будет найден, запрос будет отброшен.