Еще раз практика устранения неполадок с высокой нагрузкой на производственный ЦП

Java
Еще раз практика устранения неполадок с высокой нагрузкой на производственный ЦП

предисловие

Несколько дней назад я открыл почтовый ящик и получил электронное письмо с сигналом тревоги: загрузка ЦП 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 см.официальная документация.

Так как я забыл сделать скриншот раньше, то здесь я прихожу к прямому выводу:

Самая загруженная зеленая нитьGCThread, что означает, что он занят сборкой мусора.

представление 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Сделайте снимок для анализа.
  • Делайте выводы, корректируйте код, тестируйте результаты.

Наконец, я надеюсь, что все не получат производственные тревоги.

Ваши лайки и репост - лучшая поддержка для меня