Как отладить JBoss или PostgreSQL из-за проблем с памятью? - PullRequest
1 голос
/ 03 января 2011

Я пытаюсь отладить JBoss из-за проблемы с памятью.Когда JBoss запускается и работает какое-то время, кажется, что он использует память в соответствии с конфигурацией запуска.Однако кажется, что когда предпринимаются какие-то неизвестные действия пользователя (или размер файла журнала увеличивается до определенного размера) с использованием единственного веб-приложения, которое обслуживает JBoss, объем памяти резко увеличивается, а JBoss зависает.Когда JBoss зависает, трудно остановить процесс или что-либо сделать из-за нехватки памяти.

Когда процесс окончательно завершается с помощью аргумента -9 и сервер перезапускается, файл журнала очень мал и содержит только выходные данные при запуске недавно запущенного процесса, а не информацию о том, почему объем памяти увеличилсятак много.Вот почему так сложно отлаживать: server.log не содержит информации о прерванном процессе.Размер журнала увеличивается до 2 ГБ, а размер файла журнала для нового процесса составляет всего около 300 КБ, хотя при нормальных условиях памяти он растет должным образом.

Это информация о конфигурации JBoss:JBoss (MX MicroKernel) 4.0.3JDK 1.6.0 обновление 22PermSize = 512mMaxPermSize = 512mXms = 1024MXmx = 6144mЭто основная информация о системе:Операционная система: CentOS Linux 5.5Ядро и процессор: Linux 2.6.18-194.26.1.el5 на x86_64Информация о процессоре: Intel (R) Xeon (R) CPU E5420 @ 2,50 ГГц, 8 ядерЭто хороший пример информации о системе в обычных условиях предварительного замораживания через несколько минут после запуска службы jboss:Запущенные процессы: 183Средняя загрузка процессора: 0,16 (1 мин) 0,06 (5 мин) 0,09 (15 мин)Загрузка процессора: 0% пользователь, 0% ядро, 1% ввода-вывода, 99% простояРеальная память: 17,38 ГБ, 2,46 ГБВиртуальная память: всего 19,59 ГБ, использовано 0 байтМестное дисковое пространство: всего 113,37 ГБ, использовано 11,89 ГБКогда JBoss зависает, системная информация выглядит так:Запущенные процессы: 225Средняя загрузка процессора: 4,66 (1 мин), 1,84 (5 мин), 0,93 (15 мин).Загрузка процессора: 0% пользователь, 12% ядро, 73% ввода-вывода, 15% простояРеальная память: 17,38 ГБ, 17,18 ГБ использованоВиртуальная память: всего 19,59 ГБ, 706,29 МБ использованоМестное дисковое пространство: всего 113,37 ГБ, использовано 11,89 ГБ

================================================================

ОБНОВЛЕНИЕ К ЭТОМУ ВОПРОСУ ДОБАВЛЕНО НИЖЕ

Большое спасибо за ваши комментарии.Мы публикуем обновление этого вопроса, которое, скорее всего, будет полезно.

В 3 других случаях проблемы с памятью использование утилиты unix top указывает на то, что процесс JBoss - это процесс, который потребляет всю память.Когда проблема возникает, кажется, это происходит очень быстро.Например, после того, как JBoss в течение некоторого времени работает нормально (например, несколько дней), в какой-то момент пользователи предпринимают определенные таинственные действия, после которых может потребоваться 1-3 минуты для увеличения потребления памяти до уровня, который вызывает значительное снижение производительностии еще 5-10 минут для того, чтобы это ухудшение стало серьезным (например, трудно выполнить простые команды bash через ssh).Конечно, этот шаблон немного различается в зависимости от того, что пользователи делают в веб-приложении.

Например, при сортировке по памяти в одном случае процесс JBoss имеет следующую статистику (обратите внимание, чтореальная память - 17,38 ГБ, а JBoss - всего 6 ГБ):VIRT (общая виртуальная память): 23,1 гRES (резидентный размер набора): 15 г% ЦП: 111,3%% MEM: 97,6%

В этом же примере через 9 минут процесс JBoss имеет следующую статистику:VIRT (общая виртуальная память): 39,1 гRES (резидентный размер набора): 17 г% ЦП: 415,6%% MEM: 98,4%

После завершения процесса JBoss с помощью сигнала SIGKILL (-9) новый процесс JBoss имеет статистику, подобную следующей:VIRT (общая виртуальная память): 7147 мRES (резидентный размер набора): 1,3 г% ЦП: 11,6%% MEM: 7,3%

Теперь, когда мы знаем, что процесс JBoss потребляет всю память, мы хотим выяснить, куда он движется.Мы пробовали jmap с помощью команды, такой как jmap -dump: file = / home / dump.txt 16054 , однако это, кажется, делает сервер намного менее отзывчивым, и через некоторое время кажется, что ничего не происходит (например, подсказкане возвращается).Мы предполагаем, что так мало памяти доступно и куча настолько велика, что-то зависает.

Кроме того, мы устанавливаем параметры JVM -XX: + HeapDumpOnOutOfMemoryError -XX: HeapDumpPath = / path / to / dumps при запуске JVM, но, кажется, ничего не записывается в путь при возникновении проблемы с памятью.

Эти другие варианты были предложены:[1] используйте pmap для составления списка адресного пространства процесса и поиска больших кусков (особенно больших кусков, имеющих имя [anon])[2] отправлять SIGQUIT (kill -QUIT) процессу несколько раз подряд и искать общие следы стека[3] используйте jstack для получения дампа потока с помощью команды, такой как jstack> tdump.out [4] возитесь с JBoss Management Tools / Console, входящим в комплект JBoss, и смотрите, какие объекты остаются, когда объект начинает поглощать память.[5] исследовать Nagios как еще одно решение для мониторинга

Вот несколько дополнительных вопросов:
* Из приведенной выше информации в отчете есть какие-либо новые идеи или мысли по поводу проблемы?* Для вышеуказанных опций 1-5, которые наиболее вероятно будут работать в условиях крайне низкого объема памяти, которые создает проблема?* Для указанных выше вариантов 1-5, которые наиболее вероятно будут работать в течение очень короткого периода времени, который проблема позволяет диагностировать (например, 1-3 минуты)?* Есть ли способ автоматически записать в текстовый файл отметку времени, когда использование памяти конкретным процессом достигает нескольких определенных процентных пороговых значений, чтобы эту отметку времени можно было использовать при просмотре файлов журнала JBoss?* Есть ли способ автоматически отправлять электронное письмо с отметкой времени, когда использование памяти определенным процессом достигает нескольких определенных процентных порогов, чтобы мы могли использовать его для более целенаправленного мониторинга?

Ответы [ 3 ]

2 голосов
/ 04 января 2011

Я уже работал над этими типами проблем с помощью этого базового процесса:

  1. установить параметры JVM -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/dumps при запуске JVM.
  2. запустить приложение, дождаться сбоя (или вызвать его, если можете), собрать дамп (файл .hprof)
  3. Просмотреть дамп в Eclipse Memory Analyzer (MAT) , в котором есть симпатичный «Отчет о подозреваемых утечках»
  4. В отчете, как мы надеемся, говорится что-то вроде: «82 302 экземпляра класса XYZ занимают 74% пространства кучи». После этого вы можете проверить некоторые из этих объектов, если вам нужна дополнительная информация.

Надеюсь, этого будет достаточно, чтобы, по крайней мере, указать вам правильное направление, чтобы найти утечку.

Счастливая отладка!

1 голос
/ 04 января 2011

Этой информации недостаточно для диагностики.

Но давайте начнем с того, что имеем. Я не знаю, что вы используете, чтобы показать статистику памяти, но она показывает, что ваше общее потребление системной памяти подскочило на 15 ГБ. Что странно, учитывая, что вы дали JBoss только 6 ГБ кучи.

Итак, первое, что нужно сделать, это убедиться, что JBoss является актуальной проблемой. Самый простой способ сделать это - top, сортировка по общему объему виртуальной памяти (VIRT) или по размеру резидентного набора (RES). Чтобы изменить поле сортировки, введите заглавную букву «F», а затем выберите поле на следующем экране.

Если это процесс JBoss, который потребляет всю эту память, то вам нужно выяснить, куда он идет. Возможности включают большие отображаемые в память JAR-файлы, буферы вне кучи, выделенные через Java, и память, выделенную из собственного модуля. Поскольку у вас будет идентификатор процесса сверху, используйте pmap, чтобы составить список адресного пространства процесса, и ищите большие куски (особенно большие куски, которые имеют имя [anon]).

Если неясно, где выделяется память, вы всегда можете отправить SIGQUIT (kill -QUIT) процессу, который запишет дамп потока в stderr (который либо пойдет на консоль, либо - надеюсь, - в лог-файл). Сделайте это несколько раз подряд и найдите общие следы стека.


На основании ваших обновлений, показывающих рост виртуального размера процесса JBoss, я считаю, что изучение кучи Java - пустая трата времени. Хотя я полагаю, что JVM может игнорировать параметр -Xmx, это крайне маловероятно.

Так что это означает, что рост происходит в памяти без кучи. Некоторые возможности:

  • Использование прямых ByteBuffer с. Если вы используете буферы для кэширования результатов из базы данных, то вполне возможно, что вы выделяете слишком много буферов. Это будет диагностироваться через pmap, ища большие [anon] блоки.
  • Неконтролируемое создание потоков. Каждый поток требует некоторого количества места для своего стека потока. Я не ожидал бы, что это будет проблемой, потому что объем пространства для потока является крошечным (iirc, под 1 МБ); Вы должны были бы создать десятки тысяч из них. Вы можете диагностировать это с помощью pmap, ища небольшие блоки [anon] или отправив SIGQUIT в JVM.
  • Собственный код, который выделяет много памяти в куче Си. Вероятно, вы можете диагностировать с помощью pmap, но первым шагом является проверка ваших зависимостей, чтобы увидеть, есть ли собственная библиотека. И если есть, отладка с gdb или эквивалентным.

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

0 голосов
/ 03 января 2011

Одним из решений является использование удаленного JMX для сервера JBoss с VisualVM (входит в последнюю версию JDK).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...