Запись исключения статуса соединения TCP

задняя часть сервер Netty Tomcat

описание проблемы

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

Lottor Server запускает два порта: 9666 — порт контейнера Tomcat, а 9888 — порт сетевого сервера. Проверьте состояние порта с помощью следующей команды:

netstat -apn

порт службы netty

netstat -apn|grep 9888

Сначала проверьте порт сервера netty, соединение нормальное и не имеет ничего общего с проблемой, которую мы описали выше. Исключите подключение службы netty.

Порт контейнера Tomcat

Далее проверяем состояние порта контейнера Tomcat:

netstat -apn|grep 9666

Обнаружено большое количество соединений с состояниями FIN_WAIT2 и CLOSE_WAIT.

image

Кроме того, вы можете просмотреть текущее количество подключений с помощью следующей команды:

netstat -apn|grep 9666 | wc -l

Если углубиться дальше, можно увидеть, что количество подключений в состояниях FIN_WAIT2 и CLOSE_WAIT сопоставимо.

ПТС махнул четыре раза

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

image

Активное отключение соединения может происходить как на стороне клиента, так и на стороне сервера. Обычно используются три состояния: ESTABLISHED указывает на связь, TIME_WAIT указывает на активное завершение работы, а CLOSE_WAIT указывает на пассивное завершение работы.

ESTABLISHED

В начале и клиент, и сервер находятся в состоянии ESTABLISHED, затем клиент или сервер инициируют активное завершение работы, а другой конец пассивно закрыт.

FIN_WAIT1

Когда одна сторона получает сигнал от приложения на отключение, она отправляет дейтаграмму FIN для активного отключения, и соединение переходит в состояние FIN_WAIT1, а управление соединением переходит к ядру, и программа больше не будет его обрабатывать. При нормальных обстоятельствах состояние обработки соединения FIN_WAIT1 длится только в течение короткого периода времени.

CLOSE_WAIT

После того, как пассивно закрытый конец получает пакет FIN, его состояние CLOSE_WAIT означает, что он пассивно закрыт.

FIN_WAIT2

Когда запрос FIN активной стороны отключения отправляется и соответствующий запрос ACK успешно получен, он переходит в состояние FIN_WAIT2. На самом деле состояния FIN_WAIT1 и FIN_WAIT2 ожидают дейтаграмму FIN другой стороны. Когда TCP поддерживает это состояние, другая сторона может никогда не отключиться, что приведет к сохранению соединения.

TIME_WAIT

Из приведенной выше диаграммы перехода состояния закрытия соединения TCP видно, что сторона, которая активно закрылась, перейдет в состояние TIME_WAIT после отправки сообщения подтверждения (ACK) в сообщение FIN другой стороны. Состояние TIME_WAIT также известно как состояние 2MSL. Значение MSL — это максимальное время жизни пакета в сети. В результате четыре кортежа (IP-адрес и порт клиента, IP-адрес и номер порта сервера), определяющие это соединение, не могут использоваться, пока соединение TCP ожидает соединения 2MSL.

Анализ причин

После представления соответствующего состояния четырех взмахов рук TCP в предыдущем разделе мы проанализируем, при каких обстоятельствах соединение находится в состоянии CLOSE_WAIT? В случае пассивного закрытия соединения соединение находится в состоянии CLOSE_WAIT, когда FIN получен, но собственный FIN не отправлен. Вообще говоря, продолжительность состояния CLOSE_WAIT должна быть короткой, как и состояние SYN_RCVD. Однако в некоторых особых случаях соединение будет находиться в состоянии CLOSE_WAIT в течение длительного времени.

Есть много явлений close_wait, основная причина в том, что другая сторона в некоторых случаях закрывает соединение сокета, но другой конец не закрывает соединение, потому что он читает и пишет. Код должен оценить сокет.Как только он прочитает 0, разорвите соединение, чтение вернет отрицательный результат, проверьте errno, и если это не СНОВА, разъедините.

Файловые дескрипторы, выделяемые пользователю Linux, ограничены, и если сохраняются два состояния TIME_WAIT и CLOSE_WAIT, это означает, что соответствующее количество каналов всегда будет занято. запросы не могут быть обработаны. , за которыми следует большое количество исключений Too Many Open Files, что приводит к сбою tomcat. Посмотреть решение слишком много TIME_WAITСлишком много TIME_WAIT.

Распространенные причины ошибок

В принципе, поскольку Socket сервера не вызывает close, когда клиент закрылся, соединение сервера находится в "приостановленном" состоянии, в то время как клиент находится в состоянии ожидания ответа. Типичной особенностью этой проблемы является то, что один конец находится в состоянии FIN_WAIT2, а другой конец — в состоянии CLOSE_WAIT. Конкретно:

1. Соединение не закрывается на уровне кода.Например, в блоке finally не прописан закрывающий код для закрытия.Если в программе возникнет исключение, то закрывающий код будет пропущен.Естественно инструкция не выдается на закрыть соединение. Соединение всегда управляется программой, и ядро ​​не имеет права его обрабатывать. , естественно, запрос FIN не выдается, в результате чего соединение все время находится в состоянии CLOSE_WAIT.

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

Проблемы в лото

В Lottor клиент периодически обновляет локально сохраненную адресную информацию сервера Lottor, в частности, каждые 60 секунд, и получает результат через запрос HttpClient. Основываясь на информации, найденной в Интернете, и приведенном выше анализе, автор сначала пытается отключить периодическое обновление и наблюдать за количеством подключений к порту 9666 сервера Lottor. Количество подключений, которые росли линейно, прежде чем остановились, и изначально была обнаружена основная причина проблемы.

Сервер A является сервером сканера. Он использует простой HttpClient для запроса apache на сервере ресурсов B для получения файловых ресурсов. При нормальных обстоятельствах, если запрос выполнен успешно, сервер A будет активно отправлять запрос на закрытие соединения после обхода ресурса. , на этот раз нужно активно закрыть соединение, мы видим, что состояние соединения сервера А — TIME_WAIT. Что делать, если возникает исключение? Предполагая, что запрошенный ресурс не существует на сервере B, тогда сервер B выдаст запрос на закрытие соединения в это время.Сервер A пассивно закрывает соединение.Если сервер A пассивно закрывает соединение, программист забывает позволить HttpClient освободить соединение. соединение, что вызовет состояние CLOSE_WAIT.

Сценарий автора такой же, как и в приведенной выше ситуации.Решение этой проблемы заключается в том, что мы должны напрямую вызывать разрыв соединения при обнаружении исключения, чтобы предотвратить продолжение состояния CLOSE_WAIT. Дело можно найти вПул соединений HttpClient выдает много ConnectionPoolTimeoutException: тайм-аут, ожидающий устранения неполадок исключения соединения. Более поздний метод улучшения, предложенный автором, состоит в том, чтобы переписать логику этой части, которая вызывается и выполняется Spring Cloud FeignClient, чтобы избежать утомительных операций, таких как предыдущий запрос балансировки нагрузки.

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

微信公众号

Ссылаться на

  1. Пул соединений HttpClient выдает много ConnectionPoolTimeoutException: тайм-аут, ожидающий устранения неполадок исключения соединения
  2. Не удалось разорвать сетевое подключение — CLOSE_WAIT
  3. Подробное объяснение трехстороннего рукопожатия TCP и четырехсторонней волны