LINUX.ORG.RU
решено ФорумAdmin

Узнать побольше данных про открытые приложением сокеты

 , , ,


0

2

Привет!

Есть невероятно криво написанное серверное приложение (гремучая смесь Scala и Java, JVM, в общем, приправленное кучей библиотек).

Есть там какая-то утечка. Открываются какие-то сокеты, и потом не закрываются. Когда они заканчиваются, оно предсказуемо падает с too many open files.

Это мало кого смущает в этом бессмысленном беспощадном мире облачных вычислений. Сервер просто заменяется каким-то демоном после того как перестаёт отвечать на запросы и всё. И работает дальше. До следующего падения.

Но мне не даёт покоя, хочу разобраться, что же там внутри такое происходит. Где именно ошибка, драйвер ли это базы данных, или какой-то HTTP-клиент, или HTTP-сервер. Для своего саморазвития хочу больше разобраться.

Команда lsof -p pid выдаёт невероятное число строчек с «Can’t identify protocol».

java    (pid) (пользователь) *000u  sock                0,8       0t0 (номер) can't identify protocol

Если точнее, то

lsof -p pid | grep -c  "can't identify protocol"

Выдаёт огромное число, более 65000.

Что дальше тут можно раскопать? Как определить всё-таки протокол? Если это TCP, то можно ли как-то, например, узнать, удалённый IP-адрес и порт, к которому эта программа подключается, если это клиентский сокет? Или это может быть и серверный?

Это сетевой сокет, который закрыт с той стороны, но не с твоей. Информации о нём в ядре уже нет. Хз, как такое дебажить.

Legioner ★★★★★ ()

Недавно отлаживал подобное, только утечка была в файловых дескрипторах.

Помог strace с ключом -k (печатать стектрейсы). Можешь добавить -f для дочерних процессов и/или -e, дабы ограничить множество системных вызовов (но с осторожностью).

Далее из вывода strace можно получить native stacktrace, который чаще всего можно преобразовать в java stacktrace.

Далее отладчик, breakpoint, profit.

P. S. Коммерческие профайлеры типа YourKit и JProfiler имеют ряд встроенных метрик типа «незакрытые файлы» или «незакрытые соединения». Можно попробовать — возможно, найдёшь решение за короткое время.

P. P. S. Можно попробовать с инструментами типа JMC/JFR или VisualVM (доустановив из сети модули расширения).

Bass ★★★★★ ()
Последнее исправление: Bass (всего исправлений: 1)
Ответ на: комментарий от maxcom

Спасибо.

К сожалению, netstat их не показывает. В смысле, показывает гораздо меньше список, точно меньше чем 65000+.

Видимо, и правда.

Информации о нём в ядре уже нет. Хз, как такое дебажить.

:-(

BattleCoder ★★★★★ ()
Ответ на: комментарий от Bass

Видимо, у меня какой-то неправильный strace, пишет, что не узнаёт опцию -k.

$ strace -V
strace -- version 4.8
$ cat /etc/issue
Amazon Linux AMI release 2018.03
Kernel \r on an \m

Amazon Linux - что-то на базе старенькой CentOS.

BattleCoder ★★★★★ ()
Ответ на: комментарий от spoilt

Перезапускать надо, я так понимаю. А поймать этот плавающий баг сложно. Происходит не всегда…

BattleCoder ★★★★★ ()
Ответ на: комментарий от Bass

Вот я что смог сделать, вытащил memory dump через jmap, скопировал его на свой ноутбук, и уже открыл в visualvm.

И вижу, например, более миллиона объектов класса java.net.SocksSocketImpl и примерно столько же java.net.Socket. Памяти кушают немного, но в штуках их наверное многовато, так быть не должно, предположу?

BattleCoder ★★★★★ ()

Всем спасибо, будем считать тему решённой.

Что я сделал - в первую очередь достал номер файлового дескриптора из команды lsof -p pid.

Потом сделал memory dump, а уже из него долго кропотливо вытаскивал по номеру экзампляр класса java.io.FileDesriptor, смотрел, что на него ссылается, какой именно Socket Input/Output Stream, потом уже какой сокет, а из него вытащил, какой host/port.

Всё через VisualVM.

Как и подозревал, проблема в незакрытом соединении mysql. Осталось понять, почему это происходит, и как это исправить, но это уже другая история!

BattleCoder ★★★★★ ()
Ответ на: комментарий от BattleCoder

Извини, что не ответил — слишком поздно увидел. Ключ -k появился в версии 4.21 (13 февраля 2018).

Рад, что тебе удалось решить проблему.

Bass ★★★★★ ()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.