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

Стоит ли беспокоиться о зависании сокетов при установке тайм-аута keep-alive на бесконечность?

Некоторый исходный контекст для этого вопроса. В настоящее время у меня есть кластер приложений, развернутый за ALB, который поддерживает постоянные соединения с приложением. Это приложение постоянно находится под большой нагрузкой и должно иметь очень долгое время безотказной работы. ALB отправил обратно 502 кода состояния неверного шлюза от этой службы. Копаем глубже и после захвата pcap и sysdig на затронутых экземплярах мы видим следующее (упорядоченное по последовательности событий):

19:51:26.881806  10.23.34.195    10.23.67.39 HTTP    1068    POST /api HTTP/1.1  (application/json)
19:51:26.881838  10.23.67.39 10.23.34.195    TCP 66  80→52026 [ACK] Seq=7201 Ack=19033 Win=67072 Len=0 TSval=240987 TSecr=1566420
19:51:27.018305861 0 node (2989) > writev fd=120(<4t>10.23.34.195:52026->172.17.0.2:3000) size=400
19:51:27.018326  10.23.67.39 10.23.34.195    HTTP    466 HTTP/1.1 200 OK  (application/json)
19:51:27.018341806 0 node (2989) < writev res=400 data=HTTP/1.1 200 OK..Content-Type: application/json; charset=
19:51:27.018601  10.23.34.195    10.23.67.39 TCP 66  52026→80 [ACK] Seq=19033 Ack=7601 Win=47360 Len=0 TSval=1566454 TSecr=241021
19:51:32.042525  10.23.34.195    10.23.67.39 HTTP    1066    POST /api HTTP/1.1  (application/json)
19:51:32.042538  10.23.67.39 10.23.34.195    TCP 66  80→52026 [ACK] Seq=7601 Ack=20033 Win=69120 Len=0 TSval=242277 TSecr=1567710
19:51:32.066469320 0 node (2989) > close fd=120(<4t>10.23.34.195:52026->172.17.0.2:3000)
19:51:32.066470002 0 node (2989) < close res=0
19:51:32.066487  10.23.67.39 10.23.34.195    TCP 66  80→52026 [RST, ACK] Seq=7601 Ack=20033 Win=69120 Len=0 TSval=242283 TSecr=1567710

Как указано выше, похоже, что наше приложение nodejs достигает 5 секунд бездействия в поддерживающем соединении (период ожидания по умолчанию), затем получает сетевой запрос, затем закрывает сокет и, наконец, отвечает на поставленный в очередь сетевой запрос с помощью RST .

Таким образом, похоже, что ошибки 502 возникают из-за состояния гонки, когда новый запрос получен от балансировщика нагрузки между или во время разрыва TCP.

Наиболее очевидное решение этой проблемы - гарантировать, что балансировщик нагрузки является источником истины при разрыве этих подключений, гарантируя, что время простоя балансировщиков нагрузки меньше таймаута на сервере приложений. Это решение работает с классическими балансировщиками нагрузки AWS, но не с ALB, как указано в их документах:

Вы можете установить значение тайм-аута простоя как для балансировщиков нагрузки приложений, так и для классических балансировщиков нагрузки. Значение по умолчанию - 60 секунд. При использовании Application Load Balancer значение времени ожидания простоя применяется только к интерфейсным подключениям.

http://docs.aws.amazon.com/elasticloadbalancing/latest/userguide/how-elastic-load-balancing-works.html

Может ли кто-нибудь предположить, почему AWS, возможно, удалил тайм-аут простоя серверной части (я предполагаю, что это бесконечность)? Я мог бы также установить для тайм-аута сохранения активности на сервере узла значение Infinity, но следует ли мне беспокоиться об утечке сокетов? Могут ли они использовать какие-либо другие серверные технологии, которые решают эту проблему более изящно, чтобы исправить эту проблему (без использования классических балансировщиков нагрузки)?

Также служба поддержки AWS заявляет, что они не будут уважать заголовок Keep-Alive, отправленный обратно из службы.

Не кажется разумным полагать, что ALB держит внутренние соединения открытыми бесконечно, а скорее, что настраиваемый Тайм-аут применяется только к интерфейсным соединениям.

Меня немного беспокоит, сколько времени прошло между приездом и ACK запроса по адресу: 32.042 и закрытие fd по адресу: 32.066. Вы отключаете соединение, которое, возможно, на самом деле не простаивает - он принял запрос на 24 мс раньше. (!?) Для меня это на удивление «долгое» время.

Как указано на той же странице в документации,

Классические балансировщики нагрузки используют предварительно открытые соединения, а балансировщики нагрузки приложений - нет.

Вам не нужно беспокоиться об утечке дескрипторов, поскольку ALB не будет открывать соединения, которые ему на самом деле не нужны для обслуживания запросов ... но вам также не нужно бесконечное время ожидания.

Вопрос, по-видимому, заключается в том, как долго ALB держит открытыми незанятые внутренние соединения - что, похоже, недокументировано, но я просмотрю свои журналы и посмотрю, смогу ли я найти доказательства того, что может быть установлен таймер, если он статичен. (Удержание внутренних соединений открытыми, конечно, предназначено для оптимизации производительности.)

Интуиция подсказывает, что вы можете попробовать 75-секундный таймер на своей стороне. Это значения по умолчанию, которые я установил на основе классического поведения балансировщика, и я не заметил никаких проблем с ALB, вставленными на их место.

Мы не можем знать причину, по которой у них этого нет. Мы не можем знать решения по дизайну / реализации AWS, которые вызывают такое поведение. Только люди, которые работают с Amazon над этой функцией, знают, и они, скорее всего, находятся под соглашением о неразглашении.

Ваш единственный шанс получить достоверный ответ - это спросить AWS.