Устранение неполадок в соединениях, застрявших в состоянии CLOSE_WAIT - PullRequest
22 голосов
/ 12 апреля 2011

У меня есть приложение Java, работающее в WebLogic 11g под Windows, которое через несколько дней перестает отвечать на запросы. Один подозрительный симптом, который я заметил, заключается в том, что большое количество соединений (около 3000) отображается в netstat со статусом CLOSE_WAIT, даже когда сервер не используется. Поскольку сервер приложений управляет клиентскими подключениями, я не уверен, что является причиной этого. Мы также делаем несколько вызовов веб-сервисов, которые возвращаются на один и тот же сервер, но я считаю, что эти соединения закрываются должным образом. Что еще может вызвать это и как устранить проблему, подобную этой?

Ответы [ 6 ]

18 голосов
/ 20 апреля 2011

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

Позвольте мне сказать несколько слов, но прежде чем сказать, что я не программист на Java.

Я не буду объяснять, что такое close_wait, поскольку Брайан Уайт уже сказал все, что следует сказать.

Чтобы избежать close_wait, вам нужно убедиться, что ваш сервер не закрывает соединение после отправкиверните ответ, потому что тот, кто отключится первым, застрянет в close_wait и time_wait.Итак, если ваш сервер застревает в close_wait, он сообщает мне, что он отключается после отправки ответа.

Вы должны избежать этого, выполнив несколько действий.

1 - Если ваш клиентприложение не использует протокол http 1.1, вы должны настроить его на использование этого из-за опции заголовка 'keep-alive http.

2 - Если ваш клиент работает с http 1.1 и это не работает, или, если вынеобходимо использовать http 1.0, необходимо установить свойство заголовка запроса на подключение:

connection: keep-alive

Это говорит серверу, что ни клиент, ни сервер не должны отключаться после выполнения запроса.Благодаря этому ваш сервер не будет отключаться после каждого полученного запроса.

3 - В вашем клиенте повторно используйте сокет.Если вы создаете много клиентов сокетов в цикле, например, вы должны создать сокет один раз, и они используют его каждый раз, когда вам нужно отправить запрос.Подход, который я использовал в своем приложении, заключается в том, чтобы иметь пул сокетов и получить один доступный сокет (который уже подключен к серверу и имеет свойство keep-alive).Затем я использую его, и когда я закончу, я положу его обратно в бассейн для повторного использования.

4 - Если вам действительно нужно отключиться после отправки запроса, убедитесь, что ваш клиент делает это, и оставьте connection: keep-alive.

И да, у вас может бытьпроблемы, когда у вас много close_waits или time_waits на стороне сервера.

Проверьте эту [ссылку] [1], которая объясняет, что такое keep-alive.

Надеюсь, это было полезно.С этими вещами мне удалось решить мою проблему.

[1]: http://www.w3.org/Protocols/HTTP/1.1/draft-ietf-http-v11-spec-01.html#Persistent Соединения

17 голосов
/ 20 апреля 2011

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

Когда удаленный хост закрывается (отправляет FIN),Ваше локальное приложение получит какое-то событие (это событие «чтения» в сокете в базовой библиотеке C), но чтение из этого соединения вернет ошибку, указывающую на то, что соединение закрыто.На этом этапе локальное приложение должно закрыть соединение.

Я мало что знаю о Java и ничего не знаю о WebLogic, но, полагаю, вполне возможно, что приложение неправильно обрабатывает ошибку чтения и, следовательно, никогда не закрывает соединение.

4 голосов
/ 15 апреля 2011

Статус CLOSE_WAIT означает, что другая сторона инициировала закрытие соединения, но приложение на локальной стороне еще не закрыло сокет.

Похоже, у вас есть ошибка в вашем локальном приложении.

2 голосов
/ 29 октября 2011

Проблема заключалась в ошибке, вызванной установкой «Использовать JSSE SSL» в true в webLogic.Использование собственной реализации SSL вместо JSSE в WebLogic не является проблемой для нашего приложения, поэтому я просто снял этот флажок и проблема исчезла.

1 голос
/ 04 октября 2013

Это может означать, что вы не вызываете "close" на сокете из вашего вызова accept ().

1 голос
/ 12 апреля 2011

Я нашел эту цитату о скоплениях CLOSE_WAIT: «Что-то либо препятствует прогрессу в сеансе HTTP (мы застряли, поэтому никогда не заканчиваем вызовом close), либо была введена какая-то ошибка, которая препятствует закрытию сокета.Есть несколько способов, которыми это может произойти. "

Подумайте: может ли ваше приложение зависнуть при обработке запроса?Или сам WebLogic?

Изучите: Можете ли вы сделать дампы потоков Java (для этого можно использовать kill -SIGQUIT в Oracle JVM для Linux), чтобы попытаться выяснить, не застряли ли в действительности какие-либо из ваших потоков?

Проверьте клиентскую сторону: сначала выясните IP-адрес или имя хоста клиентов, которые подключены к сокетам CLOSE_WAIT.Затем посмотрите, происходит ли что-либо подозрительное на этих клиентах.

...