Windows server tcp timeout



Modified on: Fri, 31 May, 2024 at 3:41 PM


Overview

Problems exist where a network dropout or a computer failure will ‘lock’ a terminal, and the user will not be able to log into System Five until the lock is reset. This is a Windows issue that can be easily resolved.

Update the TCP/IP value to 3 minutes

The default Microsoft Windows timeout value for improperly disconnected TCP/IP connections is two (2) hours.  By changing the TCP/IP timeout value on the server you can reduce the delay from the default two(2) hours to three (3) minutes. This also configures the network to heal in a few minutes without requiring an administrator or support call. 

This needs to be done on the server, NOT the workstations.

  1. Open the Microsoft Windows Registry Editor ( START / RUN / Regedit <enter> )

  2. Browse to the “HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters” key

  3. Locate the Value “KeepAliveTime”. If it does not exist, create a new REG_DWORD Value called “KeepAliveTime”

  4. Set the Value “KeepAliveTime” to decimal 180000 (this is 3 minutes)

  5. Exit the registry editor

  6. Reboot your server for the changes to take effect (this reboot can be done at the end of the day or during a scheduled server reboot, but this new key won’t become active until the server is rebooted).

Please be aware that the capitalization in KeepAliveTime is important!

Registry edit screenshot:

Alternate Solution

While it is possible to use the Zen Monitor Utility to delete these sessions, it is generally not recommended as it can be easy to accidentally remove the wrong user or all users.  


Did you find it helpful?
Yes

No

Send feedback

Sorry we couldn’t be helpful. Help us improve this article with your feedback.

Related Articles


    Thank you for choosing Windward Software

    Всем привет, меня зовут Вадим Макеров, я работаю в iSpring бэкенд-разработчиком.

    Мы разрабатываем систему управления обучением (LMS — learning management system) iSpring Learn. Внутри система представляет из себя модульный монолит на PHP с почти сотней микросервисов на Go. Мы используем Kubernetes, Service Mesh, gRPC и прочие модные технологии :) Сейчас я работаю во внутренней команде Core, которая занимается внутренними улучшениями нашей системы.

    Однажды у нас в продукте был инцидент, который привел к даунтайму LMS и происходил несколько раз, в течение нескольких дней. Причина оказалась нетривиальной и находилась на уровне сетевых настроек подключений между сервисами.

    В ходе расследования пришлось погрузиться в особенности TCP-стека и его работе с gRPC.

    Чтобы статья читалась легче, описание TCP-стека упрощено без потери содержательности.
    Статья может быть полезна бэкенд-разработчикам, которые хотят узнать о работе сетевой системы более подробно.

    План

    1. Деградация приложения и зависание на 15 минут

    2. Технические причины проблемы

      • Полуоткрытое соединение 

      • 15 ретрансмитов

    3. 3 проверенных решения проблемы

      • Тонко настроить ядро

      • gRPC Keepalive

      • TCP_USER_TIMEOUT

    4. Как применять решения на практике

      • Настроить оптимальные параметры

      • Внедрить интеграцию с Service Mesh

      • Проставить конфигурацию вручную

    5. Заключение и выводы

    Деградация приложения и зависание на 15 минут

    Рассмотрим кейс, который был в нашем приложении. Выделим для рассмотрения часть с 4-мя сервисами:

    Сервисы B,C,D обращаются к компоненту A по gRPC. Каждый имеет несколько реплик (для упрощения иллюстраций они будут опущены до момента их необходимости)

    Из общей схемы системы становится понятно, что A — это некий критичный узел. В реальности это может быть брокер, база данных, сервис — любое подключение по keep-alive или долгоживущему соединению. В нашем случае важна критичность компонента A: B,C,D не могут корректно работать без A.

    При отказе одной из реплик A мы ожидаем, что остальные компоненты переключат трафик с отказавшей реплики на другую живую реплику.

    Ожидаем получить что-то такое

    Ожидаем получить что-то такое

    Но в реальности наблюдаем следующее:

    Сервисы B,C,D не переключили gRPC-соединение с реплики A , соединения остались и новые RPC по этим соединениям вставали в очереди.
    B,C,D перестали отвечать на некоторые клиентские запросы, тк трафик с реплики A1 не был переключен.

    Далее будем рассматривать только сервис B для простоты — однако B, C, D ждёт одинаковая судьба — просто в разные периоды времени.

    B не переключил часть трафика с реплики A, текущие RPC по gRPC зависли.
    На продолжительный промежуток времени запросы начинают зависать больше чем, на 2 секунды.

    На графике: зависание запросов

    На графике: зависание запросов

    Одному из сервисов повезло ещё меньше: его время зависания достигает 50 секунд (в реальности это другой кейс):

    На графике: малые столбы это те кейсы, где запросу удалось пробиться в живую реплику компонента A

    На графике: малые столбы это те кейсы, где запросу удалось пробиться в живую реплику компонента A

    gRPC фреймворк так же не понял, что что-то произошло с репликой A и продолжает отправлять ей новые запросы по зависшим (или имеющимся) соединениям.

    При большом потоке запросов на сервисы B,C,D очередь запросов в мертвую реплику заставит B,C,D истощаться по ресурсам. К примеру, это может быть ограниченное количество воркеров, оперативная память. Истощение ресурсов может привести к двум исходам.

    Первый:
    Из-за повышенного потребления ресурсов обработка остальных запросов сервисами B,C,D значительно замедлится, а запросы, которые попали в очередь запросов на мёртвую реплику, упадут по таймауту

    Второй:

    1. Постепенное истощение ресурсов компонентов

    1. Полный отказ B,C,D

      При некорректно настроенной балансировке gRPC запросов (или вообще ее полном отсутствии) приближение такой ситуации можно кратно ускорить.
      Т.к. в данном случае gRPC трафик  между репликами может идти в совершенно рандомном распределении или вообще идти на одну реплику.

    Попробую ответить на очевидно возникающий сейчас вопрос в форме диалога с читателем:
    Читатель: «Почему такое не происходит, когда я делаю редеплой приложения в кубере или допускаю segmentation fault в программе и происходит экстренное завершение?»
    Автор: «За вас отправляют по соединению FIN-пакет»

    Технические причины

    Полуоткрытое соединение

    Особенность gRPC в использовании долгоживущих соединений и мультиплексирование запросов по одному соединению, т.е. по одному соединению может проходить последовательно несколько RPC.
    Из-за чего, если отправка по соединению останавливается — gRPC продолжает копить RPC на это соединение. Тем самым в приложении истощаются ресурсы и воркеры.

    gRPC — это Application level протокол, он никак не проверяет соединение на транспортном уровне, надеясь на надежность TCP. Если на уровне TCP соединение зависло — gRPC никак на это не отреагирует.
    В таком случае, стоит спуститься на уровень TCP-соединения, чтобы понять, что происходит, когда разрывается соединение, без уведомления другой стороны.

    Рассмотрим два Linux хоста, соединенные TCP-соединением.

    Два Linux хоста, соединенные TCP-соединением. Пунктирные линии обозначают границы TCP-соединения

    Два Linux хоста, соединенные TCP-соединением. Пунктирные линии обозначают границы TCP-соединения

    Внезапно второй хост умирает.

    Второй хост умирает без уведомления первого. В TCP если хост хочет закрыть соединение, то сначала он должен уведомить другую сторону FIN-пакетом. Но в этом случае FIN-пакет не был отправлен.

    В таком случае, что произойдёт с TCP-соединением у первого хоста ?
    В TCP, когда соединение закрыто с одной из сторон и состояние соединения не синхронизировано между хостами, оно становится полуоткрытым соединением (Half-Opened)

    Но что должно произойти с операционной системой, чтобы она не отправила FIN-пакет перед закрытием соединения?

    "ауф"

    «ауф»

    В действительности нет гарантий, что другой хост отправит FIN перед закрытием соединения или пакет достигнет адресата. Провод между нодами кубер-кластера в дц просто перережут ножом или как-то ещё разорвут соединение на физическом уровне. Способов порвать соединение на уровне системы ещё больше — случаи могут быть разные.

    Скрытый текст

    Ремарка про NAT и AWS, Google Cloud proxy
    Если соединение происходит за NAT или через Proxy облачных провайдеров, то эти системы способны определить жесткое отключение пира и отправить клиенту FIN самостоятельно. В нашем кейсе между системами не было облачного прокси или настроенного NAT, как обычном необлачном K8S кластере 

    В нашем реальном кейсе — упала worker-нода из-за бага в ядре (произошёл segmentation fault и система упала) …несколько раз.

    Если с сетью что-то произошло, приложение должно уметь обрабатывать эти сценарии или быть сконфигурировано для этого.
    Один из способ избежать Half-opened соединений — настроить TCP_KEEPALIVE.

    Скрытый текст

    TCP_KEEPALIVE работает за счет отправки по соединению специальных зонд-пакетов, на которые другой хост должен ответить ACK-пакетом.
    TCP_KEEPALIVE имеет следующие настройки:

    • SO_KEEPALIVE = 1 — включить отправку keepalive зондов

    • TCP_KEEPIDLE = 5 — отправить первый зонд спустя 5 бездействия

    • TCP_KEEPINTVL = 3 —  отправить следующий зонд через 3 секунды

    • TCP_KEEPCNT = 5 — закрыть соединение после 4 неудачных попыток

    Таким образом, в случае того, если соединение станет Half-opened, оно будет закрыто через:
    TCP_KEEPIDLE + TCP_KEEPINTVL * TCP_KEEPCNT = 20 секунд.

    Пока по TCP-соединению нет активности — TCP-стек с ним ничего не делает, соединение повиснет и утечет.
    К примеру, если такие соединения образуются на сервере (к примеру, Websocket или gRPC сервер), они быстро может привести к утечке памяти и файловых дескрипторов.
    Настройка является частым best-practice (рекомендации к redis-server ставить TCP_KEEPALIVE) и может быть  установлена по умолчанию, в том же redis-server TCP_KEEPALIVE предустановлен по умолчанию.

    В таком случае, при установке TCP_KEEPALIVE в кейсе выше произойдет следующее:

    По истечению таймаута TCP_KEEPALIVE TCP стек разорвёт соединение, клиентское приложение получит от ядра ошибку — ETIMEDOUT.
    Однако одной настройки параметра TCP_KEEPALIVE недостаточно.

    В том кейсе клиенты обращались по соединению в уже мертвый хост.
    Со стороны TCP это выглядит так, что очередь на отправку постоянно растёт, а когда у соединения есть пакеты в очереди на отправку — TCP_KEEPALIVE перестаёт работать.

    Заметки на полях: во время наших инцидентов у нас был выставлен TCP_KEEPALIVE и он действительно не помог :)

    15 ретрансмитов

    Чтобы решить проблему 15-ти минут, нужно выяснить её корни.

    В кейсе выше у первого хоста есть очередь на отправку и он отправляет пакеты на ту сторону. В TCP на каждый отправленным пакет, должен прийти пакет подтверждения получения, ACK-пакет. В нашем случае, на отправленные пакеты не приходит подтверждение с той стороны — пакет «теряется».

    В TCP получение пакета другой стороной должно быть подтверждено специальным ACK-пакетом. Когда пакет не подтверждается второй стороной, происходит повторная передача неподтвержденных пакетов или  Retransmission (далее по статье процесс буду называть ретрансмит). Повторная отправка происходит по RTO (retransmission timeout).

    Т.к. второй хост мёртв, первый будет непрерывно повторять отправку пакетов. Количество повторных отправок пакетов в Linux задаётся настройкой net.ipv4.tcp_retries2 и по умолчанию равно 15. По их истечении будет закрыто соединение.

    При этом RTO динамический и экспоненциально увеличивается после каждого ретрансмита.

    15 ретрансмитов при постоянно увеличивающемся RTO дают примерный таймаут в ~15 минут.
    Таким образом и получаются 15 минут ожидания по соединению до его закрытия.

    Наглядная сводная таблица роста RTO в зависимости от номера ретрансмита:

    Взято со статьи

    Взято со статьи

    Также в статье есть описание алгоритма подсчёта RTO

    Способы решения

    Таймауты на уровне приложения

    Очевидный и понятный способ ограничить ожидание приложением какой-то сетевой задержки могут быть  application timeouts. Суть в том, что устанавливаются HTTP таймауты на запрос или Deadline в случае gRCP на RPC. В таком случае, возникают следующие проблемы:

    Универсального таймаута со стороны приложения не существует
    Для каждого RPC или запроса в приложении допустимы разные значения задержек:
    К примеру, RPC  на авторизацию операции в системе недопустимо не отвечать более 30 секунд. А вот некоторым сложным SQL-запросам может быть дозволительно работать более 30 секунд, если это происходит в фоне.
    Таким образом нужно всем запросам индивидуально выставлять таймауты, чтобы корректно срабатывать при сетевых проблемах. В крупной системе подобрать и выставить всем запросам корректный application таймаут может быть очень дорого.

    Потеря медленных клиентов 
    При наличии сетевых задержек, но при этом общей работоспособности сети, медленные клиенты начнут чаще отваливаться, хоть и сеть до них стабильна.

    (прим. Application таймауты применимы в том случае, если мы хотим форсировать, чтобы система укладывалась в соблюдение задержки на RPC в определенный сервис или ограничивать медленные запросы по API свыше определенного порога)

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

    Тонко настроить ядро

    Первая идея, которая приходит в голову, при понимании откуда берутся 15 минут ожидания — уменьшить количество повторов до с 15 до 7.

    Меняется значение через sysctl

    sysctl net.ipv4.tcp_retries2=7 

    В таком случае значение ретрансмитов станет 7 для всей системы (если применить в docker,cri контейнерах, то изменения будут применены в рамках только контейнера)

    Но у данного решения есть несколько минусов:

    System-wide
    Если приложение ходит во внешнюю сеть и активно обращается внутри кластера — количество ретрансмитов будет одинаково в любом направлении. Хотелось бы для соединений внутри кластера иметь меньшее количество повторов и быстрее реагировать на сетевые изменения, а во внешний интернет — иметь большее количество ретрансмитов, чтобы не терять менее стабильных клиентов.

    Зависимость от sysctl
    Необходимо доставить sysctl в pod/контейнер приложения. Что заставляет запускать контейнер от root пользователя. К тому же, добавляет ещё один cli инструмент или вообще невозможно реализовать при использовании distroless образов.
    Правда даже такое ограничение можно обойти: при деплое приложения в кубернетес можно воспользоваться init-контейнером для конфигурирования сети приложения — тогда нет необходимости в sysctl в основном контейнере.

    Мы решили не идти в эту сторону, т.к. конфигурирование через sysctl могло иметь множество особенностей, про которые мы могли не знать.

    gRPC Keepalive

    В поисках причин зависания и решения мы нашли настройку gRPC Keepalive (grpc.io) — мы же столкнулись с такой проблемой при использовании gRPC, значит возможно можно найти решение через gRPC. Данная опция gRPC клиента и сервера позволяет им обмениваться HTTP/2 пингами для проверки стабильности соединения (подробнее про Keepalive рассказывали коллеги из ozon в своей статье )

    Мы решили опробовать Keepalive, чтобы защитить межсервисные соединения.

    По умолчанию gRPC keepalive клиент не отправляет пинги, отправку делает только сервер раз в 2 часа.
    Такие настройки нам не походили: мы хотели, чтобы обе стороны проверяли статус соединения, а сервер чаще отправлял пинги.

    В рамках тестирования Keepalive выставили клиенту и серверу следующие значения:

    • KEEPALIVE_TIME=30s — отправляем пинги каждые 30 секунд

    • KEEPALIVE_TIMEOUT=10s — ждём ответный пинг 10 секунд

    • PERMIT_KEEPALIVE_WITHOUT_CALLS=1 — соединение проверяется даже без активных RPC

    В первом тестировании такое решение помогло (прим. мы научились вызывать segmentation fault внутри ядра, чтобы симулировать инцидент). 

    Спустя 30 секунд после падения сервера клиент отправлял пинг и, не получив на него ответ, закрывал соединение.

    Но есть ложка дёгтя:
    При первом же тестировании получали значительное количество ошибок от Go реализации (прим., мы преимущественно используем Go, поэтому будут референсы оттуда), когда были обращения в сервисы, чьи gRPC сервера не были сконфигурированы. Получали следующее:

    code: ErrCodeEnhanceYourCalm 
    debugData: too_many_pings

    Причина оказалась в настройке gRPC сервера: у него есть своя политика защиты сервера от чрезмерных пингов или EnforcementPolicy.

    Скрытый текст

    Про EnforcementPolicy 

    Такой термин присутствует только в Go реализации (в C реализации, нет на момент 12.2024), так что термин неофициальный.
    Go реализация содержит отдельную структуру конфигурации для сервера:

    type EnforcementPolicy struct {  
    //...   
    MinTime time.Duration // The current default value is 5 minutes.
    //...  
    PermitWithoutStream bool // false by default.  
    }  

    В остальных реализациях EnforcementPolicy просто разложен на два параметра:

    • PERMIT_KEEPALIVE_TIME — MinTime в Go

    • PERMIT_KEEPALIVE_WITHOUT_CALLS — PermitWithoutStream в Go

    Дальше по тексту я буду использовать термины из документации

    По значениям по умолчанию в EnforcementPolicy сервер может принимать пинги только раз в 5 минут. (прим. Технически, там дозволительно два, но это уже скорее как некая опция, позволяющая клиенту отправить дополнительный пинг из-за разницы во времени между сервисами)
    Если любой клиент нарушает эту политику, сервер отправляет ему ErrCodeEnhanceYourCalm и сразу закрывает соединение, прерывая все текущие RPC.

    Проблема решается достаточно просто — выставляется PERMIT_KEEPALIVE_TIME на стороне сервера в 30s, равный KEEPALIVE_TIME для клиента.

    В этом случае возникает несколько нюансов:

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

    Гарантированный сбой при изменении PERMIT_KEEPALIVE_TIME
    Т.к. политику формирует сервер, при деплое клиента раньше сервера — клиент будет получать ErrCodeEnhanceYourCalm .
    В Go реализации есть корректировка, если клиент получил too_many_pings, он удваивает свой KEEPALIVE_TIME. В таком случае, чтобы прийти к одинаковому значению KEEPALIVE_TIME между клиентской и серверной стороной, нужно допустить несколько сбоев. К примеру, для KEEPALIVE_TIME в 30s  нужно 4 сбоя.
    Таким образом, при выставлении gRPC Keepalive в системе, сервер должен деплоиться первым.
    У gRPC Keepalive нет API или доп протокола (как xDS для балансировки и Service Discovery), чтобы сервер и клиент могли согласовать свои параметры PERMIT_KEEPALIVE_TIME и KEEPALIVE_TIME.

    Некорректное использование Keepalive
    По поводу опасности и неправильного применения gRPC Keepalive есть issue на гитхабе в gRPC-go  — в этом посте автор критикует то, как работает Keepalive и даже предложил убрать эту фичу с клиентской стороны (чего не сделали). Он даёт ссылки на proposal-ы gPRC по Keepalive(A8-client-side-keepalive.md и A9-server-side-conn-mgt)  и наталкивает на мысль:
    gRPC Keepalive  это про поддержку соединения напрямую с клиентом на уровне L7, игнорируя промежуточные сервера (прокси, load-balancers и т.п.), где TCP проверки не сработают или невозможны.

    Такие нюансы gRPC Keepalive заставили отойти от него в пользу другого решения.

    TCP_USER_TIMEOUT

    Рассмотрим еще раз проблему на уровне TCP:
    В кейсе выше первый хост уходит в 15-ти минутные ретрансмиты, и если ограничение повторов для всей системы не подходит — возможно есть какая-то опция сокета, позволяющая ограничить повторы пакетов.

    Помимо опции TCP_KEEPALIVE tcp стек может реагировать на полуоткрытое соединение через опцию TCP_USER_TIMEOUT. 
    Рассмотрим поведение в кейсе выше при конфигурации TCP_USER_TIMEOUT=30s:

    После первого ретрансмита общее время попыток ретрансмитов ограничивается TCP_USER_TIMEOUT.
    После этого, если подтверждения не поступило, соединение закрывается с ETIMEDOUT.

    Соединение закрыто спустя TCP_USER_TIMEOUT и ресурсы первого пира освобождены от half-opened соединения.
    (прим. Значение в 30 секунд примерно соответствует времени ожидания при net.ipv4.tcp_retries2=7)

    Эта настройка решает проблему с длительным подвисанием соединения. Теперь соединение будет закрыто, если подтверждение о доставке пакета не придёт в течение 30 секунд.
    Поскольку эта настройка задаётся для каждого сокета отдельно, для разных соединений можно задать свои значения таймаутов.

    Применение

    В этой секции расскажу как мы посчитали оптимальный TCP_USER_TIMEOUT и применили его в нашей системе.

    Оптимальное значение

    Ранее по статье для примеров и моделирования использовались 7 ретрансмитов и 30s таймаута.

    Почему 7 и 30s ?

    Исходя из таблицы по подсчету RTO и количества повторенных пакетов, оптимальными значениями являются 7 повторов и 30 таймаута.

    • 7 повторов: чуть меньше половины ретраев при стандартных настройках. По сравнению с поведением по умолчанию, количество ретраев уменьшено всего в 2 раза.

    • 30 секунд: этого времени достаточно на проведение 7 повторов и оптимально, чтобы не породить сильные зависания в системе на таймаутах.
      Вот так всё просто :)

    Таймаут в 30 секунд может не подходить в следующих случаях: когда идет взаимодействие с внешним клиентом напрямую, а не через ingress. В таком случае стоит рассмотреть вариант поднять значение в TCP_USER_TIMEOUT.

    Service Mesh

    Service Mesh — инструмент, который может гарантировать единые настройки сетевого стека для всех сервисов в системе.

    Linkerd 

    Мы используем Service Mesh Linkerd — по умолчанию в нём настроены только TCP_KEEPALIVE, и нет настроек для TCP_USER_TIMEOUT (именно поэтому у нас инцидент и произошёл :) ). Пришлось самим добавлять проставление TCP_USER_TIMEOUT: issue в проекте Linkerd. Спустя месяц апрува и ревью — pull request-ы #13024 и #3174  приняли и теперь Linkerd также поддерживает TCP_USER_TIMEOUT в новом релизе.

    Теперь новая версия Linkerd защищает наш продукт от падения воркер-нод :)

    ENVOY

    В envoy же не нужно контрибьютить, достаточно настроить socket option и выставить номер опции TCP_USER_TIMEOUT. 

    Кстати, при исследовании мы так же наткнулись на issues #28865 и #33466, где пользователи envoy столкнулись с тем же инцидентом (часть графиков для демонстрации я взял из этих issue)

    Ручная конфигурация

    Если в системе отсутствует ServiceMesh или он не сконфигурирован до критичных узлов системы, опцию TCP_USER_TIMEOUT можно выставить на сокет вручную:

    func SetTCPUserTimeout(conn net.Conn, timeout time.Duration) error {  
        tcpconn, ok := conn.(*net.TCPConn)  
        if !ok {  
           // not a TCP connection. exit early  
           return nil  
        }  
        rawConn, err := tcpconn.SyscallConn()  
        if err != nil {  
           return fmt.Errorf("error getting raw connection: %v", err)  
        }  
        err = rawConn.Control(func(fd uintptr) {  
           err = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, unix.TCP_USER_TIMEOUT, int(timeout/time.Millisecond))  
        })  
        if err != nil {  
           return fmt.Errorf("error setting option on socket: %v", err)  
        }  
        return nil  
    }

    Данный код взят с grpc-go internal/syscall/syscall_linux.go

    Завершение

    Исследование и исправление причин этого инцидента, стало настоящим челленджем. Кейс зависания специфичный и просто так не гуглится. Даже сами issue на github для envoy, уже были найдены после того, как в проблеме разобрались. Предложенные решения в этих issue только подкрепляли уверенность, что все делали правильно.

    Понять корень проблемы нам помогла статья Cloudflare (перевод на хабре с дожившими до нашего времени картинками). В ней автор описывает не только кейс-ситуацию, подобную нашей, но и рассказывает важность использования TCP_KEEPALIVE. Приводит примеры работы протокола TCP с разными настройками. В этой статье намеренно опущены демонстрации экспериментов с TCP настройками, т.к. наши внутренние эксперименты на TCP_USER_TIMEOUT показывали те же результаты.

    Также хотелось бы здесь добавить какую-нибудь статистику о том, как нас спасает эта конфигурация: но за время, что она стоит, никаких инцидентов не было и срабатывать ей было незачем :)

    UPD

    В комментариях к статье @bfuvx указал на важный аспект поведения TCP.

    При восстановлении worker-ноды с сервисом A, подам были выданы те же IP-адреса, соотвественно пакеты от B,C,D должны дойти до A. В свою очередь, из-за того, что на A нет ассоциированных с этими пакетами TCP-сессий, операционная система должна отправить RST пакет, соединение со сторон B,C,D должно быть разорвано.

    Но у нас было не так, иначе не было бы статьи :)

    Как так же подсказал @bfuvxи мы с коллегами подтвердили: на всех worker-нодах стояло iptable правило, которое дропает пакеты с невалидным состоянием.

    Вот как выглядит iptables правила на каждой worker-ноде для каждого пода:

    target     prot opt source               destination
    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
    DROP       all  --  0.0.0.0/0            0.0.0.0/0            ctstate INVALID
    // остальные правила

    Интересует второе правило: оно дропает все пакеты, которые по мнению conntrack невалидные.

    Скрытый текст

    Кратко про conntrack:

    Это часть сетевого стека ядра линукс. Conntrack отслеживает состояние по соединениям и хранит его какое-то время дополнительно.

    Посмотреть размер conntrack состояния можно через conntrack-tools

    В данном случае, Conntrack помечает невалидными пакеты с сервисов B,C,D на ноде, где находится A, потому что состояние conntrack на этой ноде сброшено. Для не conntrack все выглядит так, что пакеты прилетают без старта рукопожатия из середины состояния TCP-соединения. Поэтому, conntrack дропает такие пакеты.

    Из-за того, что пакеты ушедшие на ноду A были дропнуты, операционная система не отправила в ответ B,C,D RST-пакет.
    Вот еще одна деталь почему приложение зависло :)

    Такие iptables правила ставит наш CNI в кубере и это дефолтное поведение, самостоятельно мы это не настраивали.

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

    Но такая оптимизация, порождает вот такой side-эффект, о котором вся статья :)

    Спасибо,@bfuvx за хардкорный и качественный комментарий и указание на конкретные детали!

    Applies ToWindows 7 Professional Windows 7 Ultimate Windows 7 Enterprise Windows Server 2008 R2 Datacenter Windows Server 2008 R2 Enterprise Windows Server 2008 R2 Service Pack 1 Windows Server 2008 Datacenter Windows Server 2008 Enterprise Windows Server 2008 Service Pack 2 Windows Vista Enterprise Windows Vista Service Pack 2 Windows Vista Ultimate Windows Vista Business Microsoft Windows Server 2003 Service Pack 1 Microsoft Windows Server 2003 Service Pack 2 Microsoft Windows XP Professional Microsoft Windows XP Service Pack 3 Microsoft Windows XP Service Pack 2

    Summary

    TCP starts a retransmission timer when each outbound segment is handed down to IP. If no acknowledgment has been received for the data in a given segment before the timer expires, the segment is retransmitted, up to the TcpMaxDataRetransmissions value. The default value for this parameter is 5.

    The retransmission timer is initialized to three seconds when a TCP connection is established. However, it is adjusted on the fly to match the characteristics of the connection by using Smoothed Round Trip Time (SRTT) calculations as described in RFC793. The timer for a given segment is doubled after each retransmission of that segment. By using this algorithm, TCP tunes itself to the normal delay of a connection. TCP connections that are made over high-delay links take much longer to time out than those that are made over low-delay links.

    By default, after the retransmission timer hits 240 seconds, it uses that value for retransmission of any segment that has to be retransmitted. This can cause long delays for a client to time-out on a slow link.

    For more information about the latest service pack for Windows 2000, click the following article number to view the article in the Microsoft Knowledge Base:

    260910 How to obtain the latest Windows 2000 service pack

    More Information

    Important This section, method, or task contains steps that tell you how to modify the registry. However, serious problems might occur if you modify the registry incorrectly. Therefore, make sure that you follow these steps carefully. For added protection, back up the registry before you modify it. Then, you can restore the registry if a problem occurs. For more information about how to back up and restore the registry, click the following article number to view the article in the Microsoft Knowledge Base:

    322756 How to back up and restore the registry in WindowsThe TcpMaxDataRetransmissions registry value controls the number of times that TCP retransmits an individual data segment before it aborts the connection. This value is not configured by default, but it can be entered to change the default number of retries.

    Change the following subkey in Windows 7, Windows 2008 R2, Windows 2008, Windows 2000, Windows Vista, Windows 2003, and Windows XP:

    HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Tcpip\Parameters

                Value Name:  TcpMaxDataRetransmissionsData Type:   REG_DWORD - NumberValid Range: 0 - 0xFFFFFFFFDefault:     5

    Description: This parameter controls the number of times TCP retransmits an individual data segment (non connect segment) before aborting the connection. The retransmission time-out is doubled with each successive retransmission on a connection. It is reset when responses resume. The base time-out value is dynamically determined by the measured round-trip time on the connection.

    Windows provides a mechanism to control the initial retransmit time, and the retransmit time is then dynamically self-tuned. To change the initial retransmit time, modify the following registry values.

    Change the following subkey in Windows 2003, Windows XP, and Windows 2000:

    HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\ID for Adapter

                Value Name:  TCPInitialRttData Type:   REG_DWORDValid Range: 300-65535 (milliseconds in decimal)Default:     0xBB8 (3000 milliseconds expressed in hexadecimal)

    Description: This parameter controls the initial retransmission time-out that is used by TCP on each new connection. It applies to the connection request (SYN) and to the first data segments that is sent on each connection. For example, the value data of «5000 decimal» sets the initial retransmit time to five seconds.

    NOTE: You can increase the value only for the initial time-out. Decreasing the value is not supported.

    Change the following key in Windows NT 4.0:

    HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Tcpip\Parameters

    Value Name:  InitialRttData Type:   REG_DWORDValid Range: 0-65535 (decimal)Default:     0xBB8 (3000 decimal) 

    Description: This parameter controls the initial retransmission time-out used by TCP on each new connection. It applies to the connection request (SYN) and to the first data segment(s) sent on each connection.

    For example, the value data of «5000 decimal» sets the initial retransmit time to five seconds.

    The Initial RTO in Windows Server 2008 R2 and Windows 7 is can be controlled by using the NetSH command by initialRTO.

    For prerequisites and more information, click the following article number to view the article in the Microsoft Knowledge Base:

    2472264 You cannot customize some TCP configurations by using the netsh command in Windows Server 2008 R2

    For more information about retransmit time, click the following article numbers to view the articles in the Microsoft Knowledge Base:

    232512 TCP/IP may retransmit packets prematurely

    223450 TCP Initial retransmission timer adjustment added to Windows NT

    For more information, search the web for «RFC 793 (Section 3.7) TCP Protocol Specification.»

    Need more help?

    Want more options?

    Explore subscription benefits, browse training courses, learn how to secure your device, and more.

    2022-12-04

    Do TCP connections timeout?

    The Idle Timeout setting in the TCP profile specifies the length of time that a connection is idle before the connection is eligible for deletion. If no traffic flow is detected within the idle session timeout, the BIG-IP system can delete the session. The default is 300 seconds.

    How do I change TCP timeout in Windows?

    Move to HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters. From the Edit menu select New – DWORD value. Enter a name of InitialRtt and press Enter. Double click the new value and set to the number of milliseconds for the timeout, e.g. 5000 for 5 seconds (the old default was 3 seconds).

    What is TCP timeout?

    TCP timeouts The TCP keepalive timeout defines the interval during which the TCP connection verifies that the FCIP link is working. This ensures that an FCIP link outage is detected quickly, even when the link is idle.

    What is default TCP timeout?

    By default, the TCP connection timeout is 15 minutes and the UDP connection timeout 30 seconds.

    How do I fix TCP connection timeout?

    Ways To Fix Err_Connection_Timed_Out Error

    1. Method 1: Flush DNS Cache.
    2. Method 2: Check Your Connection.
    3. Method 3: Clear Cache Memory.
    4. Method 4: Renew DNS.
    5. Method 5: Update Network Adapter Driver.
    6. Method 6: Try VPN.
    7. Method 7: Run Network Troubleshooter.
    8. Method 8: Check Antivirus And Firewall Settings.

    What causes TCP connection timeout?

    A server connection timeout means that a server is taking too long to reply to a data request made from another device. Timeouts are not a reply message: they show up when there isn’t a reply and a server request is not fulfilled in a predetermined length of time.

    How do I change my TCP connection limit?

    In the left-hand pane, click Settings and then click the Advanced tab. In the Advanced Network Engine Settings area, if Inherit is selected clear the checkbox to enable changes. Increase the value of the Maximum TCP Connections property to 10000 or more, according to your needs. Click Save.

    What causes TCP timeouts?

    Why Does Network Packet Loss Cause Service Timeouts? Network jitter can cause service timeout. This is mainly because network jitter can lead to different, varying degrees of latency. Consider TCP, which has been used in most Internet applications to this date, as an example.

    How do you troubleshoot timeout issues?

    How to Fix the ERR_CONNECTION_TIMED_OUT Error

    1. Check Your Connection. Google Chrome, Firefox, and Edge all recommend that you should check your network connection.
    2. Disable Firewall and Antivirus Software Temporarily.
    3. Disable Proxy Settings.
    4. Change DNS Servers.

    What is the maximum number of TCP connections?

    On the TCP level the tuple (source ip, source port, destination ip, destination port) must be unique for each simultaneous connection. That means a single client cannot open more than 65535 simultaneous connections to a single server. But a server can (theoretically) serve 65535 simultaneous connections per client.

    Is there a limit to how many TCP connections a host can make at once?

    Ports are 16-bit numbers, therefore the maximum number of connections any given client can have to any given host port is 64K.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    
     00:00:00.000000 IP 192.168.91.128.58368 > 192.168.91.137.6666: Flags [S], seq 2395807434, win 64240, options [mss 1460,nop,nop,TS val 3245551521 ecr 0,nop,wscale 7], length 0
     00:00:01.013807 IP 192.168.91.128.58368 > 192.168.91.137.6666: Flags [S], seq 2395807434, win 64240, options [mss 1460,nop,nop,TS val 3245552536 ecr 0,nop,wscale 7], length 0
     00:00:01.014094 IP 192.168.91.137.6666 > 192.168.91.128.58368: Flags [S.], seq 3105090969, ack 2395807435, win 65160, options [mss 1460,nop,nop,TS val 939993754 ecr 3245552536,nop,wscale 7], length 0
     00:00:01.014138 IP 192.168.91.128.58368 > 192.168.91.137.6666: Flags [.], ack 1, win 502, options [nop,nop,TS val 3245552536 ecr 939993754], length 0
     00:00:01.014253 IP 192.168.91.128.58368 > 192.168.91.137.6666: Flags [.], seq 1:1449, ack 1, win 502, options [nop,nop,TS val 3245552536 ecr 939993754], length 1448
     00:00:01.014303 IP 192.168.91.128.58368 > 192.168.91.137.6666: Flags [P.], seq 1449:2897, ack 1, win 502, options [nop,nop,TS val 3245552536 ecr 939993754], length 1448
     00:00:01.014329 IP 192.168.91.128.58368 > 192.168.91.137.6666: Flags [.], seq 2897:4345, ack 1, win 502, options [nop,nop,TS val 3245552536 ecr 939993754], length 1448
     00:00:01.014330 IP 192.168.91.128.58368 > 192.168.91.137.6666: Flags [P.], seq 4345:5793, ack 1, win 502, options [nop,nop,TS val 3245552536 ecr 939993754], length 1448
     00:00:01.014331 IP 192.168.91.128.58368 > 192.168.91.137.6666: Flags [.], seq 5793:7241, ack 1, win 502, options [nop,nop,TS val 3245552536 ecr 939993754], length 1448
     00:00:01.014367 IP 192.168.91.128.58368 > 192.168.91.137.6666: Flags [P.], seq 7241:8193, ack 1, win 502, options [nop,nop,TS val 3245552536 ecr 939993754], length 952
     00:00:01.014392 IP 192.168.91.137.6666 > 192.168.91.128.58368: Flags [.], ack 1449, win 501, options [nop,nop,TS val 939993754 ecr 3245552536], length 0
     00:00:01.014401 IP 192.168.91.128.58368 > 192.168.91.137.6666: Flags [.], seq 8193:9641, ack 1, win 502, options [nop,nop,TS val 3245552536 ecr 939993754], length 1448
     00:00:01.014419 IP 192.168.91.128.58368 > 192.168.91.137.6666: Flags [FP.], seq 9641:10001, ack 1, win 502, options [nop,nop,TS val 3245552536 ecr 939993754], length 360
     00:00:01.014498 IP 192.168.91.137.6666 > 192.168.91.128.58368: Flags [.], ack 1449, win 501, options [nop,nop,TS val 939993754 ecr 3245552536], length 0
     00:00:01.014498 IP 192.168.91.137.6666 > 192.168.91.128.58368: Flags [.], ack 1449, win 501, options [nop,nop,TS val 939993754 ecr 3245552536], length 0
     00:00:01.221646 IP 192.168.91.128.58368 > 192.168.91.137.6666: Flags [.], seq 1449:2897, ack 1, win 502, options [nop,nop,TS val 3245552743 ecr 939993754], length 1448
     00:00:01.653752 IP 192.168.91.128.58368 > 192.168.91.137.6666: Flags [.], seq 1449:2897, ack 1, win 502, options [nop,nop,TS val 3245553175 ecr 939993754], length 1448
     00:00:01.654191 IP 192.168.91.137.6666 > 192.168.91.128.58368: Flags [.], ack 5793, win 473, options [nop,nop,TS val 939994394 ecr 3245553175], length 0
     00:00:01.654217 IP 192.168.91.128.58368 > 192.168.91.137.6666: Flags [.], seq 5793:7241, ack 1, win 502, options [nop,nop,TS val 3245553176 ecr 939994394], length 1448
     00:00:01.654221 IP 192.168.91.128.58368 > 192.168.91.137.6666: Flags [P.], seq 7241:8193, ack 1, win 502, options [nop,nop,TS val 3245553176 ecr 939994394], length 952
     00:00:01.654278 IP 192.168.91.128.58368 > 192.168.91.137.6666: Flags [.], seq 8193:9641, ack 1, win 502, options [nop,nop,TS val 3245553176 ecr 939994394], length 1448
     00:00:01.654303 IP 192.168.91.128.58368 > 192.168.91.137.6666: Flags [FP.], seq 9641:10001, ack 1, win 502, options [nop,nop,TS val 3245553176 ecr 939994394], length 360
     00:00:01.654539 IP 192.168.91.137.6666 > 192.168.91.128.58368: Flags [.], ack 5793, win 496, options [nop,nop,TS val 939994394 ecr 3245553175], length 0
     00:00:01.862139 IP 192.168.91.128.58368 > 192.168.91.137.6666: Flags [.], seq 5793:7241, ack 1, win 502, options [nop,nop,TS val 3245553384 ecr 939994394], length 1448
     00:00:01.862428 IP 192.168.91.137.6666 > 192.168.91.128.58368: Flags [.], ack 7241, win 488, options [nop,nop,TS val 939994602 ecr 3245553384], length 0
     00:00:01.862444 IP 192.168.91.128.58368 > 192.168.91.137.6666: Flags [P.], seq 7241:8193, ack 1, win 502, options [nop,nop,TS val 3245553384 ecr 939994602], length 952
     00:00:01.862475 IP 192.168.91.128.58368 > 192.168.91.137.6666: Flags [.], seq 8193:9641, ack 1, win 502, options [nop,nop,TS val 3245553384 ecr 939994602], length 1448
     00:00:01.862675 IP 192.168.91.137.6666 > 192.168.91.128.58368: Flags [.], ack 7241, win 496, options [nop,nop,TS val 939994602 ecr 3245553384], length 0
     00:00:02.070061 IP 192.168.91.128.58368 > 192.168.91.137.6666: Flags [P.], seq 7241:8193, ack 1, win 502, options [nop,nop,TS val 3245553592 ecr 939994602], length 952
     00:00:02.486074 IP 192.168.91.128.58368 > 192.168.91.137.6666: Flags [P.], seq 7241:8193, ack 1, win 502, options [nop,nop,TS val 3245554008 ecr 939994602], length 952
     00:00:02.486555 IP 192.168.91.137.6666 > 192.168.91.128.58368: Flags [.], ack 10002, win 489, options [nop,nop,TS val 939995226 ecr 3245554008], length 0
     00:00:02.486557 IP 192.168.91.137.6666 > 192.168.91.128.58368: Flags [F.], seq 1, ack 10002, win 501, options [nop,nop,TS val 939995226 ecr 3245554008], length 0
     00:00:02.486636 IP 192.168.91.128.58368 > 192.168.91.137.6666: Flags [.], ack 2, win 502, options [nop,nop,TS val 3245554008 ecr 939995226], length 0
     00:00:02.717525 IP 192.168.91.137.6666 > 192.168.91.128.58368: Flags [F.], seq 1, ack 10002, win 501, options [nop,nop,TS val 939995457 ecr 3245554008], length 0
     00:00:02.717540 IP 192.168.91.128.58368 > 192.168.91.137.6666: Flags [.], ack 2, win 502, options [nop,nop,TS val 3245554239 ecr 939995226], length 0
    

    Понравилась статья? Поделить с друзьями:
    0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии
  • Ven 1022 dev 1577 windows 7 x64
  • Развернуть все окна в windows 10 горячие клавиши
  • C windows system32 dism exe
  • Utorrent запускается вместе с windows 10 как отключить
  • Драйвер для samsung r560 для windows 7