Сокеты, найденные lsof, но не netstat

У меня есть приложение, которое исчерпывает файловые дескрипторы, очевидно, открывая сокеты, но я не могу точно выяснить, что делают эти сокеты. Они появляются в выводе lsof как

java    9689 appuser 1010u  sock       0,5          263746675 can't identify protocol
java    9689 appuser 1011u  sock       0,5          263746676 can't identify protocol
java    9689 appuser 1012u  sock       0,5          263746677 can't identify protocol
java    9689 appuser 1014u  sock       0,5          263746678 can't identify protocol
java    9689 appuser 1015u  sock       0,5          263746679 can't identify protocol
java    9689 appuser 1016u  sock       0,5          263746681 can't identify protocol

и в /proc/$PID/fd как

lrwx------ 1 appuser appuser 64 Jun 23 11:49 990 -> socket:[263732085]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 991 -> socket:[263732086]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 992 -> socket:[263735307]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 993 -> socket:[263732088]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 995 -> socket:[263735308]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 996 -> socket:[263735309]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 997 -> socket:[263745434]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 998 -> socket:[263745435]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 999 -> socket:[263745436]

но нет аналогичного выхода в netstat -a,

Что это за сокеты и как я могу узнать, что они делают?

Изменить: я пытался бежать grep $SOCKET /proc/net, как рекомендовано в FAQ по lsof, где $SOCKET, например, 263746679, но это также не дало никаких результатов.


В качестве фона приложение является контейнером для множества задач, которые, помимо прочего, выполняют сетевые вызовы. Мне нужно выделить тот, который приходит в бешенство, но пока я не выясню, с кем общаются эти сокеты, я застрял.

3 ответа

Это может произойти, если вы создаете сокет, но никогда не соединяетесь с ним () или bind(). Лучше всего сделать так, чтобы приложение (-fF) связывалось с приложением, а затем делало перекрестную ссылку с выводом lsof, чтобы определить, какие сокеты вызывают проблему. В качестве бонусного метода отладки: если вы упаковываете в вызовы сокетов отладочную информацию и записываете их в /dev/null, они будут отображаться в прямом порядке, не предоставляя при этом больших файлов журналов.

Используя Python, я столкнулся с той же проблемой на сокетах SSL:

  • Когда я использую socket.close(), сокет остается в состоянии CLOSE_WAIT в течение неопределенного времени
  • когда я использую socket.shutdown(), lsof говорит: "не могу определить протокол"

Решением было развернуть слой SSL перед закрытием:

  • origsock = socket.unwrap ()
  • origsock.close ()

Это правильно закрывает сокеты в моем приложении.

Первое, что я хотел бы сделать, это вставить, если ваш файловый дескриптор ограничен:

~# vi /etc/sysctl.conf
fs.file-max = 331287

Далее я бы хотел убедиться, что ваша система обновлена, включая все библиотеки и серверы. Возможно, ваш сервер приложений Java устарел (если вы его используете). Также возможно, что ваш сервер приложений неверно сконфигурирован, вы должны взглянуть на свой файл конфигурации и опустить свой connectionTimeout и / или ваш maxKeepAliveRequests (Я не уверен, какой сервер приложений вы используете или используете ли вы его вообще...).

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

Вот несколько способов отладки проблемы.

Wireshark (или twireshark для клиентов) - лучший инструмент, чтобы увидеть, как используются эти сокеты. Wireshark поможет вам разобраться в типе трафика, передаваемого по проводам. Вполне вероятно, что первые несколько соединений будут успешными, а затем он достигнет предела дескриптора файла. Как только предел файлового дескриптора будет достигнут, Wireshark не собирается что-либо предпринимать (и в этом отношении neater - netstat), но это поможет сузить проблему. Может случиться так, что отправляется много исходящих SYN, однако SYN/ACK не принимаются, поэтому многие соединения tcp просто застряли в состоянии SYN_WAIT.

Если у вас есть доступ к исходному коду и вы знаете тип создаваемых сокетов (например, использование strace или просто поиск по коду), вы можете открыть проект в Eclipse (или другой IDE) и установить точку останова для функции, которая создает эти сокеты. Когда достигается точка останова, вы можете посмотреть на трассировку стека. Эта утечка файлового дескриптора может быть простым бесконечным циклом или, возможно, значение времени ожидания сокета слишком велико. Другая возможность заключается в том, что приложение Java не делает socket.close() очистить соединения. Завершение обычно делается в finely блок try/catch (Да, у сокета всегда должен быть try / catch в Java, иначе он не будет собираться:). В конце концов, вполне вероятно, что приложение Java не обрабатывает свои IOException должным образом.

Другие вопросы по тегам