У меня есть приложение, которое исчерпывает файловые дескрипторы, очевидно, открывая сокеты, но я не могу точно выяснить, что делают эти сокеты. Они появляются в выводе 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, но это также не дало никаких результатов.
В качестве фона приложение является контейнером для множества задач, которые, помимо прочего, выполняют сетевые вызовы. Мне нужно выделить тот, который приходит в бешенство, но пока я не выясню, с кем общаются эти сокеты, я застрял.
Ответы:
Это может произойти, если вы создаете сокет, но никогда не соединяетесь с ним () или bind (). Лучше всего сделать так, чтобы приложение (-fF) связывалось с приложением, а затем делало перекрестную ссылку с выводом lsof, чтобы определить, какие сокеты вызывают проблему. В качестве бонусного метода отладки: если вы упаковываете вызовы сокетов в отладочную информацию и записываете их в / dev / null, они будут отображаться сразу, без больших файлов журнала.
источник
Используя Python, я столкнулся с той же проблемой на сокетах SSL:
Решением было развернуть слой SSL перед закрытием:
Это правильно закрывает сокеты в моем приложении.
источник
Первое, что я хотел бы сделать, это вставить, если ваш файловый дескриптор ограничен:
Далее я бы хотел убедиться, что ваша система обновлена, включая все библиотеки и серверы. Возможно, ваш сервер приложений Java устарел (если вы его используете). Также возможно, что ваш сервер приложений неверно сконфигурирован, вы должны взглянуть на свой файл конфигурации и уменьшить свой
connectionTimeout
и / или вашmaxKeepAliveRequests
(я не уверен, какой сервер приложений вы используете или используете ли вы его вообще ...).Я не уверен, что делает это приложение, но если вы не думаете, что для этого требуются десятки тысяч сокетов, то это почти наверняка «утечка файлового дескриптора» в вашем Java-приложении. Возможно, вам придется отправить отчет об ошибке поставщику. В этом сообщении об ошибке вы должны включить информацию о том, как воссоздать проблему.
Вот несколько способов отладки проблемы.
Wireshark (или twireshark для клиентов) - лучший инструмент, чтобы увидеть, как используются эти сокеты. Wireshark поможет вам разобраться в типе трафика, передаваемого по проводам. Вполне вероятно, что первые несколько соединений будут успешными, а затем он достигнет предела дескриптора файла. Как только предел файлового дескриптора будет достигнут, Wireshark не собирается что-либо предпринимать (и в этом отношении neater - netstat), но это поможет сузить проблему. Может случиться так, что отправляется много исходящих SYN, однако SYN / ACK не принимаются, поэтому многие соединения tcp просто застряли в состоянии SYN_WAIT.
Если у вас есть доступ к исходному коду и вы знаете тип создаваемых сокетов (например, использование strace или просто поиск по коду), вы можете открыть проект в Eclipse (или другой IDE) и установить точку останова для функции, которая создает эти сокеты. Когда достигается точка останова, вы можете посмотреть на трассировку стека. Эта утечка файлового дескриптора может быть простым бесконечным циклом или, возможно, значение времени ожидания сокета слишком велико. Другая возможность заключается в том, что Java-приложение не выполняет
socket.close()
очистку соединений. Закрытие обычно выполняется вfinely
блоке atry/catch
(да, у сокета всегда должна быть попытка / перехват в Java, иначе он не будет собираться :). В конце концов, вполне вероятно, что приложение Java не обрабатывает свои IOException должным образом.источник