предисловие
Несколько дней назад я открыл почтовый ящик и получил электронное письмо с сигналом тревоги: загрузка ЦП ip-сервера высока, пожалуйста, исследуйте и решите ее как можно скорее, а время отправки — раннее утро.
На самом деле, я тоже имел дело с подобной проблемой еще в прошлом году и записал ее:«Однократное устранение неполадок и оптимизация ЦП на 100%»
Однако причина этой проблемы не такая, как в прошлый раз, вы можете продолжать смотреть вниз.
анализ проблемы
Получив письмо, я сразу же зашел на сервер и увидел, что место преступления все еще там (нагрузка все еще была высокой).
Поэтому я использовал процедуру устранения неполадок для такого рода проблем, чтобы найти их снова.
первое использованиеtop -c
Отображение использования системных ресурсов в режиме реального времени (-c
параметры для отображения команды целиком).
Затем введите大写 P
Применить в соответствии сCPU
В порядке скорости использования первой является программа с самой высокой скоростью использования.
Конечно же, это один из нашихJava
применение.
Это приложение просто используется для регулярного запуска некоторых отчетов. Планирование задач будет запускаться рано утром каждого дня. В обычных условиях операция будет завершена через несколько часов.
Второй шаг нормальной работы — узнать наибольшее потребление в этом приложении.CPU
В конце концов что нить делать.
использоватьtop -Hp pid
затем введитеP
все еще согласноCPU
Использование сортирует потоки.
В настоящее время нам нужно только запомнить идентификатор потока и преобразовать его в шестнадцатеричный формат, чтобы сохранить его с помощьюjstack pid >pid.log
Создайте файл журнала, используя только что сохраненный шестнадцатеричный процесс.ID
Перейдите к этому снимку темы и выполните поиск, чтобы узнать потреблениеCPU
Что делает нить?
Если вы сочтете это хлопотным, я также настоятельно рекомендую артефакт определения местоположения проблемы с открытым исходным кодом Alibaba.arthas
чтобы найти проблему.
Например, описанную выше операцию можно свести к командеthread -n 3
Вы можете распечатать снимок трех самых загруженных потоков, что очень эффективно.
Дополнительные руководства по использованию Arthas см.официальная документация.
Так как я забыл сделать скриншот раньше, то здесь я прихожу к прямому выводу:
Самая загруженная зеленая нитьGC
Thread, что означает, что он занят сборкой мусора.
представление GC
После проверки здесь опытные водители наверняка подумают, что большинство из них вызвано проблемами с использованием памяти приложениями.
Итак, я прошелjstat -gcutil pid 200 50
Распечатайте использование памяти и состояние повторного использования gc (распечатайте 50 раз каждые 200 мс).
Из рисунка можно получить следующую информацию:
-
Eden
Район иold
Область почти заполнена, и видно, что есть проблема с восстановлением памяти. -
fgc
Частота рециркуляции очень высока, 8 рециркуляций произошло в течение 10 с ((866493-866485)/ (200 *5)
). - Длится дольше, fgc много раз случалось 8W.
анализ памяти
Поскольку начальное позиционирование — это проблема с памятью, все же необходимо выполнить анализ моментального снимка памяти, чтобы окончательно определить проблему.
по командеjmap -dump:live,format=b,file=dump.hprof pid
Файл моментального снимка можно экспортировать.
Тогда вы должны использоватьMAT
Такие аналитические инструменты имеются.
выявить проблему
Из этого рисунка видно, что в памяти находится очень большая строка, и на эту строку просто ссылается поток этой задачи синхронизации.
Подсчитано, что память, занимаемая этой строкой, составляет около 258 м, что уже является очень большим объектом для строки.
Как появилась эта струна?
На самом деле, глядя на ссылочное отношение и содержимое строки на рисунке выше, нетрудно увидеть, что этоinsert
изSQL
утверждение.
я должен восхищатьсяMAT
Этот инструмент также может помочь вам предсказать, где в моментальном снимке памяти могут возникнуть проблемы, и предоставить моментальные снимки потоков.
Наконец, конкретный бизнес-код был найден с помощью этого снимка потока:
Он вызывает метод, который записывает в базу данных, и этот метод соединяетinsert
предложение, в которомvalues
Он генерируется циклическим сплайсингом, который примерно выглядит следующим образом:
<insert id="insert" parameterType="java.util.List">
insert into xx (files)
values
<foreach collection="list" item="item" separator=",">
xxx
</foreach>
</insert>
Таким образом, когда список становится очень большим, составной оператор SQL будет очень длинным.
Только что из анализа памяти видно, что этоList
Он также очень большой, что приводит к финальномуinsert
Операторы занимают огромное количество памяти.
Стратегия оптимизации
Теперь, когда причина проблемы найдена, решить ее несложно.Есть два направления:
- Контролируйте источник
List
размер, этоList
Это также данные, полученные из некой таблицы, которые можно получить путем подкачки, чтобы последующийinsert
Сроки будут сокращены. - Контроль размера пакетной записи данных, по сути, суть сводится к сращиванию этого
SQL
длина вниз. - Общая эффективность записи нуждается в переоценке.
Суммировать
Время от анализа до решения этой задачи невелико и относительно типично Процесс суммируется:
- Сначала определите потребление
CPU
процесс. - стоимость переезда
CPU
конкретный поток. - проблема с памятью
dump
Сделайте снимок для анализа. - Делайте выводы, корректируйте код, тестируйте результаты.
Наконец, я надеюсь, что все не получат производственные тревоги.
Ваши лайки и репост - лучшая поддержка для меня