Розетки, знайдені lsof, але не netstat


19

У мене є програма, у якої не вистачає дескрипторів файлів, мабуть, відкриваючи сокети, але я не можу точно дізнатися, що роблять ці сокети. Вони відображаються у висновку 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, але це також не дало результатів.


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


З цією проблемою нещодавно ми стикаємося з одним із наших веб-додатків .NET Core (сервер Ubuntu з Kestrel), але на пристрої записано "0,9" з ім'ям "протокол: TCP". Намагатись з’ясувати, які саме пристрої 0 та 9 виявилися важкими. Але всі симптоми виглядають як один і той же випадок відкривання розеток без прив'язки та їх використання.
іслала

Відповіді:


17

Це може статися, якщо ви створили сокет, але ніколи не з'єднуйтеся з ним () або зв'язуйте (). Вашою найкращою ставкою може бути напруження програми (-fF), а потім перехресне посилання з результатом lsof, щоб визначити, які сокети викликають проблему. Як бонусний метод налагодження: якщо ви загортаєте дзвінки в сокет з інформацією про налагодження і записуєте їх у / dev / null, він з’явиться в напрузі, не даючи вам весело великих журнальних файлів.


Дякую, це звучить цікаво. Я спробую з’ясувати, чи справді це стосується нашої програми.
Роберт Мунтяну

1
Дещо за тією ж лінією, тому що це Java може бути дуже важко використовувати strace; кращим методом може бути створення власного підкласу сокета, який записує інформацію перед тим, як передавати його в батьківський (справжній) JDK-сокет. strace може бачити лише основні дзвінки Java в ОС і не може бачити всередині ваших потоків для того, що насправді робить ці дзвінки в сокет, щоб розтягнути все це виглядає як одна велика куля Java.
troyengel

@troyengel: Я (пере) відкрив для Byteman ( jboss.org/byteman ) дуже акуратний інструмент, який дозволяє мені вводити байт-код, необхідний для відстеження цих дзвінків.
Роберт Мунтяну

Найкорисніша відповідь, так це отримує щедрість. Спасибі!
Роберт Мунтяну

2

Використовуючи Python, я зіткнувся з тією ж проблемою на SSL-сокетах:

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

Рішенням було розгортання шару SSL перед закриттям:

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

Це закриває розетки належним чином у моєму додатку.


1

Перше, що я б зробив, це збільшити, якщо ваш дескриптор файлу обмежує:

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

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

Я не впевнений, що робить ця програма, але якщо ви не вважаєте, що для неї потрібні десятки тисяч сокетів, це майже напевно "витік дескриптора файлів" у вашій програмі Java. Можливо, вам доведеться надіслати звіт про помилку продавцю. У цьому звіті про помилку слід включити інформацію про те, як відтворити проблему.

Ось кілька способів налагодження проблеми.

Wireshark (або twireshark для кліпу) - найкращий інструмент, щоб побачити, як використовуються ці розетки. Wireshark допоможе вам розбити тип трафіку, який перекидається через дріт. Цілком ймовірно, що перші кілька підключень матимуть успіх, а потім вони досягнуть межі дескриптора файлу. Після того, як буде досягнуто обмеження дескриптора файлу, Wireshark не збирається брати нічого (а точніше є netstat для цього питання), але це допоможе звузити проблему. Можливо, існує випадок, коли надсилається багато вихідних SYN, однак не надходить жодне SYN / ACK, тому багато з'єднань tcp просто застрягли в стані SYN_WAIT.

Якщо у вас є доступ до вихідного коду і ви знаєте тип створюваних сокетів (наприклад, за допомогою strace або просто пошук коду), ви можете відкрити проект у Eclipse (або іншому IDE) і встановити точку перерви у функції, яка створює ці розетки. Коли точка зламу потрапить, тоді ви можете подивитися на слід стека. Цей дескриптор файлу протікає, можливо, простий нескінченний цикл або, можливо, значення часу очікування сокета занадто велике. Інша можливість полягає в тому, що програма java не робить socket.close()для очищення з'єднань. Закриття зазвичай робиться в finelyблоці try/catch(Так, у сокеті завжди має бути спроба / ловити на Java, інакше він не будується :). Зрештою, ймовірно, що програма Java не належним чином обробляє IOException.


Дякую за відповідь. Я фактично розробляю цей додаток - частину контейнера - замість того, щоб просто керувати ним, і мені не вдалося знайти жодних проблем, пов’язаних із тим, що сокети не закриваються. Але натяк на дріт-скарб / twireshark хороший, я буду використовувати це.
Роберт Мунтяну

@Robert Munteanu Якщо ви будуєте цю програму, це питання для stackoverflow. Ніколи не відкривайте занадто багато розеток.
Грак

Ладья: Я відмовився від пошуку цього кодового шляху і спробував відстежити це як систематичний адміністратор. Тому я розмістив у SF. І так, я знаю, якось занадто багато розеток відкрито. Але є нульові підказки щодо того, де ...
Роберт Мунтяну

@Robert Munteanu Вам потрібно встановити точки розриву при створенні розетки і подивитися на слід стека та пам'ять у цій точці. Я підозрюю, що ти потрапляєш у нескінченну петлю. Вміння переглядати будь-яку змінну та крок, хоча ваш код стане найкращим підходом для таких складних проблем.
Грак

На жаль, це відбувається, здавалося б, випадково на одному з 20 серверів - не завжди однаково -, лише у виробничих середовищах, і, можливо, двічі на тиждень. Інакше вивести пальці було б досить просто. В даний час я використовую Byteman ( jboss.org/byteman ) для відстеження створення сокета / прив'язки / підключення / закриття дзвінків. Сподіваємось, щось із цього вийде.
Роберт Мунтяну
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.