kind:Deploymentspec:template:spec:volumes:-name:jprofilerhostPath:path:/opt/data/jprofiler12.0.2/# на диске containers:-name:test-webserverenv:-name:JAVA_OPTIONS# свободный портvalue:-agentpath:/tmp/jp/bin/linux_musl-x64/libjprofilerti.so=port=8849,nowaitvolumeMounts:-name:jprofilermountPath:/tmp/jp# в поде
Для CentOS: linux-x64 вместо linux_musl-x64
kind:Deploymentspec:template:spec:volumes:-name:jprofilerhostPath:path:/opt/data/jprofiler12.0.2# просто linux-x64 containers:-name:test-webserverenv:-name:JAVA_OPTIONSvalue:-agentpath:/tmp/jp/bin/linux-x64/libjprofilerti.so=port=8849,nowaitvolumeMounts:-name:jprofilermountPath:/tmp/jp
Для другого сервиса можно оставить все также
kind:Deploymentspec:template:spec:volumes:-name:jprofilerhostPath:path:/opt/data/jprofiler12.0.2/# или linux_musl-x64 containers:-name:test-webserver-otherenv:-name:JAVA_OPTIONSvalue:-agentpath:/tmp/jp/bin/linux-x64/libjprofilerti.so=port=8849,nowaitvolumeMounts:-name:jprofilermountPath:/tmp/jp
Файл настроек prof.jfc сохраняется во внешний каталог
kind:Deploymentspec:template:spec:volumes:-name:jfrhostPath:path:/opt/data/jfr# Каталог /opt/data/jfr с файлом prof.jfccontainers:-name:test-webserverenv:-name:JAVA_OPTIONSvalue:>-
-XX:StartFlightRecording=disk=true,maxsize=1g,filename=/tmp/jfr/prof.jfc
-XX:FlightRecorderOptions=repository=/tmp/results,maxchunksize=1m,stackdepth=1024
volumeMounts:-name:jfrmountPath:/tmp/jfr
Тонкая настройка Java Flight Recorder
Внешний каталог с файлом монтируется в Pod
kind:Deploymentspec:template:spec:volumes:-name:jfrhostPath:path:/opt/data/jfrcontainers:-name:test-webserverenv:-name:JAVA_OPTIONSvalue:>-
-XX:StartFlightRecording=disk=true,maxsize=1g,filename=/tmp/jfr/prof.jfc
-XX:FlightRecorderOptions=repository=/tmp/results,maxchunksize=1m,stackdepth=1024
volumeMounts:-name:jfrmountPath:/tmp/jfr# Монтируем /opt/data/jfr в /tmp/jfr
Тонкая настройка Java Flight Recorder
Файл настроек prof.jfc передается в JAVA_OPTIONS
kind:Deploymentspec:template:spec:volumes:-name:jfrhostPath:path:/opt/data/jfrcontainers:-name:test-webserverenv:-name:JAVA_OPTIONSvalue:>-# Передаем путь /tmp/jfr/prof.jfc в параметр filename-XX:StartFlightRecording=disk=true,maxsize=1g,filename=/tmp/jfr/prof.jfc-XX:FlightRecorderOptions=repository=/tmp/results,maxchunksize=1m,stackdepth=1024volumeMounts:-name:jfrmountPath:/tmp/jfr
Пишем инструкцию по профилированию в ручном режиме
Масштабирование
Записываем видео с демонстрацией профилирования
Масштабирование
Парное профилирование и анализ результатов
Масштабирование
Пишем скрипты автоматизации профилирования
Масштабирование
Пишем скрипты автоматизации профилирования
Масштабирование
Примонтировать/загрузить профайлер
Настроить JAVA_OPTIONS на профилирование
Запустить профилирование
Скачать результаты профилирования
kubectl
kubectl, Web UI (Dashboard)
kubectl, Web UI (Dashboard), Lens, ...
Помещаем скрипты в CI/CD окружение: добавляем Web UI
Масштабирование
Для микросервисов задач не стало меньше
Особенности Kubernetes
Подключение профайлера к JVM в k8s
Добавь ресурсов +1 CPU и если JavaAgent, то и +1 GiByte HEAP
При большой нагрузке профилируй локально, семплированием
Для Alpine Linux выбирай musl реализации инструментов
Как выполнять анализ: от потоков к коду
Анализ
Анализ результатов профилирования
Посмотреть на потоки визуально
Собрать статистику по потокам
Детализировать работу потоков
JProfiler и YourKit также перехватывают SQL и HTTP-запросы
С SJK несложно автоматизировать формирование отчета
JDK Flight Recorder собирает огромное количество метрик
Обмен знаниями, передача опыта, автоматизация
Масштабирование
Обмен знаниями, передача опыта, скрипты
Документировать результат
Доброжелательность и терпение
Стремиться к автоматизации и регрессионному профилированию
Профилирование JVM в Kubernetes : три больших шага
Вопросы и ответы
# Масштабирование сервисов и их профилирования
Микросервисная архитектура является популярной.
Kubernetes позволяет запускать множество микросервисов и предоставляет API доступа к ним. Сотни сервисов. С каждым из которых работают разные инженеры.
Часто нужно узнать детали работы приложения в контейнере. Нужна трассировка или профилирование. А также последующий анализ результатов. И этим также будут заниматься разные инженеры.
Расскажу, как можно сделать процесс профилирования проще. Мастабировать его на все сервисы и всю команду.
# Этапы профилирования и стадии масштабирования
Для трассировки и профилирования нужно добавить внутрь контейнера специальные инструменты, которых в легковесных контейнерах нет. Часто в контейнерах нет ни JDK, ни утилит профилирования, ни утилит трассировки, ни прав админа, ни доступа к репозиториям пакетов и сети Интернет, чтобы установить недостающие пакеты.
Но выполнить профилирование можно:
- примонтировать в контейнер каталоги с файлами
- изменить параметры запуска JVM
- запустить внутри контейнера команды
- скачать из контейнера файлы с результами
Это повторяемый однообразный процесс, особенно, когда на тестовом стенде работает 100 микросервисов.
При этом, это непростой процесс. А его должна уметь выполнять вся команда. Чтобы масштабировать запуск профилирования на всю команду можно:
- написать подробную инструкцию
- выполнять профилирование по Skype/Zoom/... совместно
- автоматизировать процесс с помощью скриптов
- организовать запуск профилирования из CI/CD
Но потом понадобится анализ результатов профилирования. Анализ становится повторяемым однообразным процессом, особенно, когда на тестовом стенде работает 100 микросервисов, которые нужно регулярно профилировать.
Анализ - получение фактов, сравнимых чисел, из результатов профилирования.
При этом, это непростой процесс. А его должна уметь выполнять вся команда. Чтобы мастабировать анализ результатов профилирования на всю команду можно:
- написать подробные отчеты
- выполнять анализ профилирования по Skype/Zoom/... совместно
- автоматизировать процесс анализа результатов с помощью скриптов
- организовать анализ результатов профилирования из CI/CD
А в завершении анализа, бывает нужно сравнить текущие результаты с предыдущими. Чтобы сделать вывод - ускорился метод или нет. И этот этап также нуждается в масштабировании и автоматизации.
Таким образом выделяется четыре этапа:
1. Подготовка микросервиса к профилированию
2. Запуск профилирования
3. Анализ результатов
4. Сравнение
Каждый из которых проходит четыре стадии:
1. Описание в виде инструкции
2. Совместное выполнение с коллегой
3. Автоматизация процесса с помощью скриптов
4. Возможность запуска скриптов с помощью CI/CD
# Технологии автоматизации этапов профилироваия
Благодаря Kubernetes и инструменту kubectl, есть единый для всех сервисов способ выполнения первых двух этапов:
- Подготовка микросервиса к профилированию
- Запуск профилирования
Благодаря возможностям инструментов профилирования по запуску в консольном режиме, есть автоматизируемый способ выполнения второго и третьего этапа.
- Запуск профилирования
- Анализ результатов
И если профилирование проводилось для сервисов, работающих при схожей нагрузке, и проводилось схожим образом, то сравнить результаты профилирования можно и скриптом и в Excel и в Grafana:
- Сравнение тоже автоматизируется
Интересно, как это можно сделать?
# Kubernetes, JVM в Docker и kubectl
Популярные образы с OpenJDK от fabric8
| Name | OS | Ver | Dev? | Hit |
|---|---|---|---|---|---|
| [s2i-java](https://hub.docker.com/r/fabric8/s2i-java) | CentOS | 8/11 | JRE | 10M |
| [java-centos-openjdk8-jre](https://hub.docker.com/r/fabric8/java-centos-openjdk8-jre) | CentOS | 8 | JRE | 100k |
| [java-centos-openjdk8-jdk](https://hub.docker.com/r/fabric8/java-centos-openjdk8-jdk) | CentOS | 8 | JDK | 100k |
| [java-alpine-openjdk8-jre](https://hub.docker.com/r/fabric8/java-alpine-openjdk8-jre) | Alpine | 8 | JRE | 100k |
| [java-alpine-openjdk8-jdk](https://hub.docker.com/r/fabric8/java-alpine-openjdk8-jdk) | Alpine | 8 | JDK | 100k |
| [java-alpine-openjdk11-jre](https://hub.docker.com/r/fabric8/java-alpine-openjdk11-jre) | Alpine | 11 | JRE | 100k |
Небольшое разнообразие.
Кроме таких JVM также применяется IBM OpenJ9.
С помощью kubectl можно:
- менять Deployment-файл
- монтировать каталоги в контейнер
- менять JAVA_OPTIONS
- добавлять javaAgent
- открывать JMX/RMI-порты
- менять другие параметры запуска JVM
- копировать файлы в контейнер
- получать доступ до сетевых портов контейнера
- запускать команды внутри контейнера
- копировать файлы из контейнера
Это все, что нужно для запуска и получения результатов профилирования.
# JVM профайлеры
У популярных инструментов и технологий профилирования есть консольный режим запуска:
- JDK Flight Recorder c утилитой jcmd или параметрами запуска JVM
- SJK с подключением по JMX/RMI или по PID-процесса
- AsyncProfiler с утилитой jattach или JVM агентом
- JProfiler с утилитой jpenable или JVM агентом
- YourKit с утилитой yjp-controller-api-redist.jar и JVM агентом
У профайлеров есть разные варианты сбора событий:
- JDK Flight Recorder собирает внутренние события JVM
- SJK использует семплирование
- AsyncProfiler использует семплирование
- JProfiler использует и семплирование и инструментацию
- YourKit использует и семплирование и инструментацию
Выделяется три варианта сбора событий по длительности работы кода:
- внутренние события
- семплирование
- инструментация
Инструментация требует значительных накладных расходов, большое приложение может проходить инструментацию, предшествующую началу профилирования от 20 до 60 минут. И приложение значительно замедляется при выполнении профилирования с инструментацией.
Таким образом для повседневного профилирования рекомендется использовать подход JDK Flight Recorder со сбором внутренних событий JVM, почти без накладных расходов. И подход с семплированием потоков с небольшими накладными расходами.
# Визуальный анализ результатов
- Java Mission Control для JFR-файлов
- Flame-диаграммы в SJK
- Flame-диаграммы в AsyncProfiler
- JProfiler GUI и экспорт в HTML в JProfiler
- YourKit GUI и экспорт в HTML в YourKit
# Анализ и сравнение результатов
Также есть программный и консольный режим анализа результатов профилирования, превращения файла с результатами профилирования в числа, записанные в текстовом формате:
- Для jfr-файлов от JDK Flight Recorder и AsyncProfiler:
- OpenJDK Mission Control Java API для работы с jfr
- SJK jfr2json с сохранением в JSON
- SJK ssa для allocation и exception с сохранением в TXT и CSV
- Для sdt-файлов от SJK:
- SJK ssa с сохранением в TXT и CSV
- SJK dexp c сохранением в CSV
- Для JProfiler:
- jpexport с сохранением в XML и CSV
- Для YourKit:
- консольный экспорт в XML, CSV, TXT
Для анализа нужны как визуальные так и числовые результаты профилирования. Чтобы такие результаты получить надо будет запустить консольные команды и скрипты с различными параметрами.
Разработкой таких скриптов и предлагаю заняться.
# Сравнение результатов
Инструменты профилирования позволяют сохранять результат в CSV-формат. А данные в формате CSV удобно сравнивать.
Для сравнения результатов достаточно данных:
- по активности потоков
- по активности прикладных методов
То есть сравнение не ищет узкие места, оно показывает измениласть ли длительность работы потоков и методов, и если изменилась, то они стали работать меньше или больше.
# Хранение результатов
Кроме сбора и анализа результатов возникает задача удобного хранения. Так, чтобы место хранения было общедоступным. Чтобы результаты можно бы было прикрепить к дефекту и отчету. Чтобы структура хранения была удобной.
Удобно хранить файловые результаты профилирования в nexus / artifactory / ... - в хранилище артефактов с веб-интерфейсом, которое обычно есть инфраструктуре разработки для JVM. А числовые результаты профилирования в PostgreSQL, InfluxDB и отображать их в Grafana - веб-интерфейс для чистовых данных, которое обучно есть в инфраструктуре тестирования производительности.
# Тестовый стенд
Соберем тестовый стенд в котором будут:
- JVM-приложение SpringBoot в Kubernetes
Не в Kubernetes будут работать:
- TeamCity Server
- TeamCity Agent, с которого будет запускаться профилирование
- TeamCity Agent, с которого будет подаваться нагрузка
- Nexus для хранения результатов
- influxdb - timeseries база данных, используется для хранения клиентских метрик
- prometheus - система мониторинга, используется для сбора и хранения метрик cadvisor
- grafana - система визуализации, используется для визуализации метрик/логов
- loki - система аггрегации логов, используется для хранения логов
- vector - коллектор логов, используется для отправки логов в loki
- cadvisor - коллектор метрик docker, используется для сбора метрик всего окружения
- github.com в качестве git-репозитория
# Настройка локального Kubernetes
https://kubernetes.io/docs/tasks/tools/
- kubectl
- minikube
git clone https://github.com/polarnik/JVM-profiling-in-Kubernetes
cd ./JVM-profiling-in-Kubernetes/services/
./setup.sh
!! Скрипт при работе удаляет кластер с именем minicube и создает его снова
- Отлдельно заострить внимание на тестовом стенде
- Подход к мониторингу на продуктиве несколько другой
- особенность работы именно в Kubernetes
- как запустить профилирование на 1 поде из 12
- как собрать результаты при падении
- почему нужно увеличить память и CPU limit
- особенность работы с Alpine
- другой способ запуска
- На каком этапе мы подключаем профилировщик
- реплики
- Java должна быть поверх Kubernetes а не наоборот
- Как мы профилируем
- Масштабирование - часть звучала обще, тут нужна конкретика про Kubernetes, показать примеры, где это нужна почему это нужно на примере облаком, нужны примеры и картинки.
- Сколько потоков нужно на два ядра - 2 или 22
- Мы управляем только потоками или ядрами
- Вместо состояний потоков
- Более явно разобрать пазл
- Картинку показывать один раз
- глибс, масл
- Бизнес-отчет
- Какой Scale нужен
- Какие Request/Limit нужны
- Какой коэффициент масштабирования
- Выводы, более явно что людям делать
- 3-4 совета
- простые и не длинные
- что сделать дальше
- к чему стремиться
- чего бояться
- где подкладывать соломку
- что будет при переходе от VM к Kubernetes
- Как сравнить Zipkin/Jaeger и JVM профайлер
- Как собрать цифры с этой системы, 0-й уровень, пусть система сама все скажет
_footer:
Изображение <a href="https://pixabay.com/ru/users/nicolaticola-2681567/?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=1736209">Nicola Redfern</a> с сайта <a href="https://pixabay.com/ru/?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=1736209">Pixabay</a>