Снижение задержки приложения Java

Оптимизация задержек в приложении на Java

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

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

Одной из техник, которую я использовал, был анализ памяти для получения информации о деятельности вокруг использования памяти в JVM. Хотя это может показаться тривиальным, я обнаружил серьезные проблемы, которые потребовали некоторого времени для их решения. В конечном итоге я смог преодолеть каждую из них и успешно уменьшил 99-перцентильную задержку приложения с 400 мс до 240 мс.

Уменьшение задержки было для меня новым вызовом, поэтому мне понадобились оптимальные инструменты для его решения. Существовало множество доступных инструментов, как бесплатных, так и платных, но я нашел инструмент анализа памяти Eclipse MAT наиболее полезным среди бесплатных. Существует множество статей о том, как установить и использовать MAT, поэтому я не буду вдаваться в подробности.

В этой статье я расскажу о проблемах, связанных с анализом памяти в крупных производственных приложениях и о том, как их преодолеть.

Проблемы

  1. Размер кучи памяти JVM в больших приложениях достаточно велик, в моем случае он составлял около 100 ГБ. Анализ такого большого дампа кучи требует большого объема памяти для выполнения инструмента анализатора и обычно происходит медленно на обычных ноутбуках.
  2. Большие дампы кучи требуют такого же объема дискового пространства. Если дискового пространства недостаточно, команда для создания дампа кучи завершится ошибкой, или в худшем случае заполнит раздел root и приведет к сбою хоста, на котором она выполняется.
  3. Создание дампа кучи вызывает блокировку всего приложения. Создание дампа кучи останавливает все действия в приложении, что может привести к ошибкам проверки работоспособности сервиса и его завершению, что затрудняет получение файла дампа кучи.

Решение

  1. В случае большого дампа кучи лучше использовать облачный ресурс, такой как AWS EC2, с достаточным объемом памяти и дискового пространства.
  2. Для решения проблемы места на диске, если приложение запущено на облачном ресурсе, обычно ему предоставляется отдельное хранилище. В таком случае объем хранилища можно увеличить перед созданием дампа кучи.
  3. Проверьте, выполняется ли проверка работоспособности приложения через определенные интервалы времени, например, если оно является частью балансировщика нагрузки. В таком случае оно должно быть исключено из рабочего набора, чтобы избежать его завершения после запуска команды для создания дампа кучи.
  4. Создавайте несколько дампов кучи через определенные интервалы времени для отслеживания изменений в состоянии сервиса.

Улучшения

  1. Одним из главных возможных источников проблем был кэш в памяти, что приводило к избыточному использованию памяти и частым сборкам мусора с задержкой.
  2. Анализ памяти дал основной подсказку о том, как использовался индекс данных, который использовался для извлечения данных. Оказалось, что полный индекс загружался в кучу JVM и также хранился на tmpfs, что использовало в два раза больше необходимой памяти, что было избыточным и также приводило к частым сборкам мусора.

Вывод

Анализ памяти для любого крупномасштабного производственного приложения критичен.

Кэширование данных внутри приложения может быть полезным, но его работоспособность должна тщательно отслеживаться по мере времени.

Анализ дампа кучи – мощный инструмент. Если он выполняется с использованием правильных машин и инструментов, он может стать проблематичным.

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

Я не углублялся в детали, чтобы статья была короткой. Если кому-то нужна дополнительная информация, не стесняйтесь писать мне.