Возникли проблемы из-за повторного использования и повторной передачи TCP-порта для HTTP-трафика.
Мое развертывание выглядит следующим образом:
У меня есть прокси-сервер squid, установленный на машине unix, которая отправляет обработку HTTP-запросов, поступающих из надежного источника. Затем Squid переадресуется URL-фильтру, в котором есть список белых и черных списков. Это механизм фильтрации URL-адресов, который разрешает / блокирует URL-адреса в соответствии с правилом.
Из клиента я запустил скрипт, который непрерывно выполняет 500 wget для www.naukri.com в цикле. Этот URL-адрес я заблокировал в системе фильтрации URL-адресов.
После нескольких запросов ~ 120 wget зависали ровно на 1 минуту. Во время этого состояния зависания я взял tcpdump на сервере и обнаружил, что он показывает «повторно используются номера портов TCP» и начинает посылать пакет синхронизации с тем же портом, который использовался ранее, и показывает «TCP Retransmisson». Также FIN, ACK и RST получены для предыдущего запроса.
Прикрепляем скриншот дампа tcp для справки:
Не могли бы вы сообщить мне, почему он использует тот же порт для нового запроса и повторно передает пакет? Есть ли способ избежать повторного использования портов?
почему он использует тот же порт для нового запроса и повторно передает пакет?
Он повторно использует один и тот же порт, потому что это более эффективно.
Здесь есть хорошее объяснение: https://stackoverflow.com/questions/14388706/socket-options-so-reuseaddr-and-so-reuseport-how-do-they-differ-do-they-mean-t
повторно передать? Что ретранслировать? Возможны повторные передачи пакетов, но эти должен быть полностью отделенным от проблемы повторного использования порта.
Я только что столкнулся с похожей проблемой. (С участием lockd
не httpd).
Проблема здесь в том, что именно ваш удаленный сервер закрыл соединение с помощью пакета FIN.
Когда он это делает, он помещает соединение в TIME_WAIT
state - который специально должен игнорировать любые дополнительные пакеты, в случае, если есть дополнительные фрагменты, которые все еще находятся в полете / идут по другим сетевым маршрутам.
Таким образом, он игнорирует дополнительные пакеты, отправленные вашим приложением, пока TIME_WAIT
истекает на сервере.
Ваш клиент не получает ACK
для этих пакетов, поэтому он повторно передает. (Которые также игнорируются, пока TIME_WAIT
истекает.
Что касается того, почему он отправил пакеты FIN? Тяжело сказать. Это зависит от сервера. Но если вы выглядели как атака отказа в обслуживании, возможно, поэтому.
Но вы действительно должны поймать CLOSE_WAIT
заявить о своем клиенте, и не повторно используйте сокет, если это произойдет.
Повторное использование TCP-портов само по себе не так уж и плохо. Как указал symcbean, он более эффективен, и это может быть так очевидно на вашем примере, потому что вы быстро открываете много новых сокетов. Я вижу на снимке экрана вашего захвата, что с момента запуска процесса прошло 2 секунды, и вы упомянули о зависании после ~ 120 подключений, что является хорошим количеством новых подключений за 2 секунды.
Повторные передачи, которые вы видите, вероятно, связаны с тем, что кто-то в сети отбрасывает от вас любые другие SYN-пакеты. 60 новых подключений в секунду с одного и того же хоста считаются опасными практически всеми администраторами сети и безопасности, и любые настройки по умолчанию на брандмауэре или даже на прокси-сервере начнут незаметно отбрасывать ваш трафик.
Если вы пытаетесь имитировать пользовательскую нагрузку, боюсь, вы делаете это неправильно. 60 новых соединений в секунду с нескольких разных хостов - это более чем нормально, но это нереально, если они исходят с одного хоста. Фактически, браузер пользователя ограничивает количество подключений к одному хосту числом от 6 до 12 одновременных (в зависимости от браузера и версии). Некоторые браузеры считают прокси-сервер одним хостом, но у других также есть другие ограничения для прокси (до 15 одновременно).
Вы можете обойти ограничения в Squid, настроив конфигурацию, но опять же, это нереальный тест.