Настройка TIME_WAIT TCP
Мы пытаемся настроить приложение, которое принимает сообщения через TCP, а также использует TCP для некоторых своих внутренних сообщений. Во время нагрузочного тестирования мы заметили, что время отклика значительно уменьшается (а затем и вовсе прекращается), поскольку в систему поступает больше одновременных запросов. За это время мы видим много TCP-соединений в TIME_WAIT
статус, и кто-то предложил понизить TIME_WAIT
переменная окружения по умолчанию от 60 секунд до 30.
Из того, что я понимаю, TIME_WAIT
Установка по существу устанавливает время, когда ресурс TCP снова становится доступным для системы после закрытия соединения.
Я не "сетевой парень" и очень мало знаю об этих вещах. Мне нужно много того, что есть в этом посте, но немного "тупо".
- Я думаю, я понимаю, почему
TIME_WAIT
значение не может быть установлено на 0, но может ли оно быть безопасно установлено на 5? Как насчет 10? Что определяет "безопасную" настройку для этого значения? - Почему по умолчанию для этого значения 60? Я предполагаю, что люди намного умнее меня имели веские основания для выбора этого в качестве разумного значения по умолчанию.
- Что еще я должен знать о потенциальных рисках и преимуществах переопределения этой ценности?
7 ответов
TCP-соединение определяется кортежем (исходный IP-адрес, исходный порт, IP-адрес назначения, порт назначения).
Причина, по которой возникает состояние TIME_WAIT после завершения сеанса, заключается в том, что на пути к вам все еще могут находиться живые пакеты в сети (или от вас, которые могут запросить какой-то ответ). Если бы вы воссоздали тот же кортеж, и один из этих пакетов обнаружился, он был бы обработан как действительный пакет для вашего соединения (и, вероятно, вызвал ошибку из-за последовательности).
Таким образом, время TIME_WAIT обычно устанавливается так, чтобы удваивать максимальный возраст пакетов. Это значение является максимальным возрастом, до которого ваши пакеты будут разрешены до того, как сеть их отбросит.
Это гарантирует, что до того, как вам разрешат создать соединение с тем же кортежем, все пакеты, принадлежащие предыдущим воплощениям этого кортежа, будут мертвыми.
Это обычно диктует минимальное значение, которое вы должны использовать. Максимальный возраст пакета определяется свойствами сети, например, время жизни спутника выше, чем время жизни ЛВС, поскольку пакеты должны пройти гораздо дальше.
Обычно только конечная точка, которая выдает "активное закрытие", должна перейти в состояние TIME_WAIT. Поэтому, если возможно, пусть ваши клиенты выдают активное закрытие, которое оставляет TIME_WAIT на клиенте, а НЕ на сервере.
Смотрите здесь: http://www.serverframework.com/asynchronousevents/2011/01/time-wait-and-its-design-implications-for-protocols-and-scalable-servers.html и http://www.isi.edu/touch/pubs/infocomm99/infocomm99-web/ для подробностей (позже также объясняется, почему это не всегда возможно из-за дизайна протокола, который не учитывает TIME_WAIT).
Пакс прав в отношении причин TIME_WAIT и почему вы должны быть осторожны при снижении настроек по умолчанию.
Лучшее решение состоит в том, чтобы изменить номера портов, используемых для исходного конца ваших сокетов. После того, как вы это сделаете, вам не придется долго ждать индивидуальных розеток.
Для прослушивающих сокетов вы можете использовать SO_REUSEADDR, чтобы позволить прослушивающему сокету связываться, несмотря на то, что сокеты TIME_WAIT сидят без дела.
В Windows вы можете изменить его через реестр:
; Set the TIME_WAIT delay to 30 seconds (0x1E)
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\TCPIP\Parameters]
"TcpTimedWaitDelay"=dword:0000001E
Установка tcp_reuse более полезна, чем изменение time_wait, если у вас есть параметр (ядра 3.2 и выше, к сожалению, который дисквалифицирует все версии RHEL и XenServer).
Отбрасывание значения, особенно для пользователей, подключенных по VPN, может привести к постоянному воссозданию прокси-туннелей на исходящем соединении. С конфигурацией Netscaler (XenServer) по умолчанию, которая ниже конфигурации Linux по умолчанию, Chrome иногда приходится воссоздавать туннель прокси до десятка раз, чтобы получить одну веб-страницу. Приложения, которые не повторяются, такие как Maven и Eclipse P2, просто не работают.
Первоначальный мотив для параметра (избегать дублирования) был сделан избыточным из-за TCP RFC, который указывает включение метки времени во все запросы TCP.
Я провёл нагрузочное тестирование серверного приложения (на linux) с помощью тестовой программы с 20 потоками.
За 959 000 циклов соединения / закрытия у меня было 44 000 неудачных соединений и много тысяч сокетов в TIME_WAIT.
Я установил SO_LINGER в 0 перед вызовом закрытия и в последующих запусках тестовой программы не было ошибок подключения и менее 20 сокетов в TIME_WAIT.
TIME_WAIT не может быть виновником.
int listen(int sockfd, int backlog);
В соответствии с томом Unix Network Programming Volume1, отставание определяется как сумма завершенной очереди подключения и неполной очереди подключения.
Допустим, осталось 5 записей. Если у вас есть 3 завершенных соединения (состояние ESTABLISHED) и 2 незавершенных соединения (состояние SYN_RCVD), и есть еще один запрос на соединение с SYN. Стек TCP просто игнорирует пакет SYN, зная, что он будет передан в другой раз. Это может быть причиной деградации.
По крайней мере, это то, что я читал.;)