У меня есть приложение, в котором заканчиваются файловые дескрипторы, по-видимому, из-за открытия сокетов, но я не могу точно узнать, что эти сокеты делают. Они отображаются в выводе 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
, как рекомендовано в lsof FAQ , где $ SOCKET - это, например, 263746679, но это тоже не дало результатов.
В качестве фона приложение представляет собой контейнер для нескольких задач, которые, среди прочего, выполняют сетевые вызовы. Мне нужно выделить тот, который сходит с ума, но пока я не выясню, с кем связываются эти сокеты, я застрял.
Это может произойти, если вы создаете сокет, но никогда не подключаете к нему connect () или bind (). Лучшим вариантом может быть strace (-fF) приложение, а затем перекрестная ссылка с выводом lsof, чтобы определить, какие сокеты вызывают проблему. В качестве бонусного метода отладки: если вы обернете свои вызовы сокетов отладочной информацией и запишете их в / dev / null, она появится в strace, не давая вам забавно больших файлов журнала.
Используя Python, я столкнулся с той же проблемой на сокетах SSL:
Решением было развернуть слой SSL перед закрытием:
Это правильно закрывает сокеты в моем приложении.
Первое, что я бы сделал, это увеличил лимит вашего файлового дескриптора:
~# vi /etc/sysctl.conf
fs.file-max = 331287
Затем я должен убедиться, что ваша система обновлена, включая все библиотеки и серверы. Возможно, ваш сервер приложений Java устарел (если вы его используете). Также существует вероятность того, что ваш сервер приложений настроен неправильно, вам следует посмотреть свой файл конфигурации и снизить connectionTimeout
и / или ваш maxKeepAliveRequests
(Я не уверен, какой сервер приложений вы используете или используете ли вы его вообще ...).
Я не уверен, что делает это приложение, но если вы не думаете, что ему требуются десятки тысяч сокетов, то это почти наверняка "утечка файлового дескриптора" в вашем приложении Java. Возможно, вам придется отправить поставщику отчет об ошибке. В этот отчет об ошибке вы должны включить информацию о том, как воссоздать проблему.
Вот несколько способов отладить проблему.
Wireshark (или twireshark для cli) - лучший инструмент, чтобы увидеть, как используются эти сокеты. Wireshark предоставит вам разбивку по типу трафика, передаваемого по сети. Вполне вероятно, что первые несколько подключений будут успешными, а затем достигнут предел дескриптора файла. Как только будет достигнут предел дескриптора файла, Wireshark не будет ничего улавливать (и более аккуратным является netstat в этом отношении), но это поможет сузить проблему. Возможен случай, когда отправляется много исходящих SYN, однако никакие SYN / ACK не принимаются, поэтому многие TCP-соединения просто застревают в состоянии SYN_WAIT.
Если у вас есть доступ к исходному коду и вы знаете тип создаваемых сокетов (например, с помощью strace или просто ищите код), вы можете открыть проект в Eclipse (или другой IDE) и установить точку останова для функции, которая создает эти сокеты. Когда достигается точка останова, вы можете посмотреть трассировку стека. Эта утечка файлового дескриптора может быть простым бесконечным циклом или, возможно, значение тайм-аута сокета слишком велико. Другая возможность заключается в том, что приложение java не выполняет socket.close()
чтобы очистить соединения. Закрытие обычно выполняется в finely
блок try/catch
(Да, у сокета всегда должна быть попытка / уловка в Java, иначе он не будет построен :). В конце концов, вполне вероятно, что приложение Java неправильно обрабатывает свои исключения IOException.