Какова стоимость многих TIME_WAIT на стороне сервера?
Вопрос
Предположим, есть клиент, который устанавливает множество кратковременных подключений к серверу.
Если клиент закроет соединение, в нем будет много портов. TIME_WAIT
состояние на стороне клиента.Поскольку у клиента заканчиваются локальные порты, быстро сделать новую попытку подключения становится невозможно.
Если сервер закроет соединение, я увижу много TIME_WAIT
s на стороне сервера.Однако приносит ли это какой-либо вред?Клиент (или другие клиенты) могут продолжать попытки подключения, поскольку у него никогда не заканчиваются локальные порты, а количество TIME_WAIT
состояние увеличится на стороне сервера.Что произойдет в конце концов?Случилось ли что-то плохое?(замедление, сбой, обрыв соединения и т. д.)
Обратите внимание, что мой вопрос не «Какова цель TIME_WAIT
?", а "Что произойдет, если их будет так много? TIME_WAIT
состояния на сервере?" Я уже знаю, что происходит, когда соединение закрывается в TCP/IP и почему TIME_WAIT
требуется состояние.Я не пытаюсь устранить неполадки, а просто хочу знать, в чем может заключаться потенциальная проблема.
Проще говоря, скажем netstat -nat | grep :8080 | grep TIME_WAIT | wc -l
принты 100000
.Что случилось бы?Замедляется ли сетевой стек операционной системы?Ошибка «Слишком много открытых файлов»?Или просто не о чем беспокоиться?
Решение
Каждый сокет в TIME_WAIT
потребляет некоторую память в ядре, обычно несколько меньше, чем сокет ESTABLISHED
, но все еще имеет большое значение. Достаточно большое количество может исчерпать память ядра или, по крайней мере, ухудшить производительность, поскольку эта память может использоваться для других целей. Сокеты TIME_WAIT
не содержат дескрипторов открытых файлов (при условии, что они были закрыты должным образом), поэтому вам не нужно беспокоиться о «слишком большом количестве открытых файлов». ошибка.
Сокет также связывает этот конкретный IP-адрес и порт src
/ dst
и порт, поэтому его нельзя использовать повторно в течение интервала TIME_WAIT
, (Это целевое назначение состояния TIME_WAIT
.) Связывание порта обычно не является проблемой, если только вам не нужно повторно подключить одну и ту же пару портов. Чаще всего одна сторона будет использовать эфемерный порт, и только одна сторона будет привязана к хорошо известному порту. Однако очень большое количество сокетов TIME_WAIT
может исчерпать эфемерное пространство порта, если вы неоднократно и часто подключаетесь между одними и теми же двумя IP-адресами. Обратите внимание, что это влияет только на эту конкретную пару IP-адресов и не влияет на установление соединений с другими хостами.
Другие советы
Результаты на данный момент:
Даже если сервер закрыл сокет с помощью системного вызова, его файловый дескриптор не будет освобожден, если он перейдет в состояние TIME_WAIT. Дескриптор файла будет освобожден позже, когда состояние TIME_WAIT исчезнет (т.е. через 2 * MSL секунд). Поэтому слишком большое количество TIME_WAIT может привести к ошибке «слишком много открытых файлов» в процессе сервера.
Я считаю, что стек O / S TCP / IP был реализован с правильной структурой данных (например, хэш-таблица), поэтому общее количество TIME_WAIT не должно влиять на производительность стека O / S TCP / IP. Пострадает только процесс (сервер), которому принадлежат сокеты в состоянии TIME_WAIT.
Каждое соединение идентифицируется кортежем (IP-адрес сервера, порт сервера, IP-адрес клиента, клиентский порт). Важно отметить, что каждое из соединений TIME_WAIT
(будь то на стороне сервера или на стороне клиента) занимает один из этих кортежей.
С TIME_WAIT
на стороне клиента легко понять, почему вы не можете устанавливать больше соединений - у вас больше нет локальных портов. Однако та же проблема относится и к стороне сервера - после того, как у него есть 64 тыс. Соединений в состоянии TIME_WAIT
для одного клиента , он не может принимать больше соединений от этот клиент , потому что он не может определить разницу между старым соединением и новым соединением - оба соединения идентифицируются одним и тем же кортежем. В этом случае сервер должен просто отправить обратно RST
для новых попыток подключения от этого клиента.
Если у вас много подключений от разных IP-адресов клиентов к IP-адресам серверов, вы можете столкнуться с ограничениями таблицы отслеживания соединений.
Проверять:
sysctl net.ipv4.netfilter.ip_conntrack_count
sysctl net.ipv4.netfilter.ip_conntrack_max
Для всех кортежей src ip/port и dest ip/port в таблице отслеживания может быть только net.ipv4.netfilter.ip_conntrack_max.Если этот лимит достигнут, вы увидите сообщение в своих журналах «nf_conntrack:таблица заполнена, пакет теряется», и сервер не будет принимать новые входящие соединения, пока в таблице отслеживания снова не появится место.
Это ограничение может коснуться вас задолго до того, как закончатся временные порты.
В моем сценарии я запустил сценарий, который несколько раз планирует файлы, мой продукт выполняет некоторые вычисления и отправляет ответ клиенту, т.е. клиент выполняет повторный HTTP-вызов для получения ответа на каждый файл. Когда около 150 файлов являются запланированными портами сокетов в мой сервер переходит в состояние time_wait, и в клиенте выдается исключение, которое открывает http-соединение, т.е.
Error : [Errno 10048] Only one usage of each socket address (protocol/network address/port) is normally permitted
В результате мое приложение зависло. Я не знаю, может ли поток потоков перешел в состояние ожидания или что произошло, но мне нужно завершить все процессы или перезапустить приложение, чтобы оно снова заработало.
Я попытался сократить время ожидания до 30 секунд, поскольку по умолчанию оно составляет 240 секунд, но оно не сработало.
Таким образом, в целом общее влияние было критическим, так как мое приложение не отвечало на запросы
похоже, сервер может просто исчерпать порты для назначения входящих соединений (на время существующих TIMED_WAIT) - случай для атаки DOS.