Допустим, у вас есть большое приложение, написанное на Java. Это может быть веб-сервлет, размещенный в контейнере, или автономный сервис.
В процессе разработки (и во время эксплуатации) возникает необходимость отслеживать процессы, происходящие в JVM: работу сборщика мусора, использование памяти, жизненный цикл потоков, а также другие показатели, специфичные для вашего проекта с помощью MBeans. Самый простой вариант — использовать профайлер.
Но увы, проблемы не случаются по расписанию, и заранее узнать, когда нужно включить профайлер, невозможно, да и держать его постоянно включенным тоже не вариант. В таких случаях непрерывный мониторинг является идеальным решением.
Вот об этом мы и поговорим.
Но сначала несколько слов о классическом профилировании.
Использование профилировщика
Пожалуй, самый простой и доступный способ мониторинга приложения.Профайлеры позволяют отслеживать состояние JVM в режиме реального времени, детально анализировать статистику ее работы, вплоть до анализа активности отдельных потоков.
На рынке есть как бесплатные, так и платные решения:
- jконсоль — утилита, входящая в дорожный набор коллекционера кофе» Инструменты и утилиты JDK " Предоставляет доступ ко всей базовой статистике JVM, включая прямую работу с MBeans.
- ВисуалВМ — продвинутые аналоги jconsole. Уже некоторое время ( когда кто-то купил кого-то ) также поставляется с jdk. Вы можете прочитать о VisualVM и основах профилирования в Эта статья .
Добавлю лишь, что если вам нужно подключить профилировщик к JVM на удаленном сервере, но вы не хотите заморачиваться, то просто найдите на нем бинарник VisualVM, а затем вызовите его по ssh с трансляцией X-сессии :
ssh -X login@domain /usr/bin/jvisualvm
- JПрофилер — лидер среди коммерческих профайлеров (если у кого-то есть большой опыт использования, буду рад взять на вооружение).
Непрерывный мониторинг
У профайлеров есть один существенный недостаток — вы не можете держать их открытыми 24 часа в сутки, 7 дней в неделю.Он просто не предназначен для этого.
Зачем нужен такой мониторинг? Тогда вы никогда не знаете, когда в вашем приложении возникнут проблемы.
Непрерывный мониторинг позволяет выполнить сводный анализ статистики за день, день, месяц и сделать первоначальные предположения о причинах некорректной работы сервиса/приложения на основе графиков использования памяти, потоков и других метрик.
Например, вы проводите QA-тесты ночью, а утром анализируете поведение сервиса на основе непрерывного мониторинга.
Готовых систем с приемлемым сочетанием цены и качества я не нашел, поэтому, имея большой опыт работы с Заббикс Я решил адаптировать его под свои нужды (для тех, кто знаком с Zapcat, несколько слов о нем будет в конце статьи).
Вы можете сразу спросить: «Почему Zabbix, а не ZabbixЭ» Нагиос ? Я люблю готовые продукты, которые работают «из коробки» и не требуют ручной доводки и стыковки модулей.
Итак, приступим к приготовлению сервера ;-)! Для приготовления блюда «Непрерывный мониторинг JMX с помощью Zabbix» нам понадобится:
- Ubuntu Server 10.04 (в качестве заменителей можно использовать Debian и RedHat)
- PostgreSQL или MySQL по вкусу
- Забфикс-сервер
- Забфикс-клиент
- Oracle Java (скрипты в этой статье ориентированы на JVM HotSpot)
- Джолокия (мост JMX-HTTP) — помогает избежать проблем с настройкой соединений JMX RMI.
Быстрая настройка Zabbix
Если у вас уже есть настроенный Zabbix-сервер с подключенными для мониторинга клиентскими машинами, то вы можете сразу переходить к следующему шагу.Сервер и агент Zabbix можно установить либо из репозитория, либо скомпилировать из исходного кода.
Обычно репозитории содержат очень старые версии zabbix; для тестов они тоже подойдут, но для повседневного использования рекомендую что-то поновее.
Итак, устанавливаем из репозитория: sudo apt-get install zabbix-agent zabbix-server-pgsql zabbix-frontend-php php5-pgsql tomcat6
После установки заходим в локальный хост/забфикс Войдите в систему как администратор с паролем Zabbix. Перейдите на вкладку «Конфигурация -> Хосты» и нажмите «Сервер Zabbix».
Измените статус с «Не отслеживается» на «Наблюдается».
Далее открываем в редакторе файл /etc/zabbix/zabbix_agentd.conf и заменяем его содержимое на предложенное: Server=127.0.0.1
Hostname=redcraft
StartAgents=16
DisableActive=1
EnableRemoteCommands=1
DebugLevel=4
Timeout=30
PidFile=/var/run/zabbix-agent/zabbix_agentd.pid
LogFile=/var/log/zabbix-agent/zabbix_agentd.log
В пользовательском интерфейсе Zabbix перейдите в «Мониторинг -> Последние данные» и убедитесь, что данные начали собираться с локальной машины.
На этом базовая настройка Zabbix завершена, переходим к подготовке JMX.
Подключение JVM-агентов Jolokia
Мы будем использовать Tomcat в качестве экспериментальной JVM. Чтобы подключаться к нему не по протоколу RMI, а использовать HTTP, воспользуемся мостом JMX-HTTP Jolokia. Доступно для tomcat на официальном сайте.Переименуйте загруженный файл war в jolokia.war и поместите его в /var/lib/tomcat6/webapps. Перезапустите кота.
Открытие адреса локальный хост :8080/jolokia и, если все сделали правильно, видим следующую информацию: {"timestamp":1328444565,"status":200,"request":{"type":"version"},"value":{"protocol":"6.1","agent":"1.0.2","info":{"product":"tomcat","vendor":"Apache","version":"6.0.24"}}}
Если у вас автономное приложение, то для подключения к нему jolokia необходимо добавить в строку запуска следующий параметр: -javaagent:$LIBDIR/jolokia-agent.jar=port=9090,host=localhost
Где $LIBDIR/jolokia-agent.jar — путь к JVM-агенту Jolokia
Настройка сбора данных с помощью Jolokia
Теперь у нас есть Zabbix и JVM с подключенным к нему мостом JMX-HTTP. Необходимо организовать сбор данных.
Схема сбора данных будет выглядеть так:
Объясню, почему я не собираю метрики напрямую, а использую промежуточный буфер.
Если настроить схему без него, то при каждом запросе будет запускаться скрипт сбора статистики JMX, что является более ресурсоемкой операцией, чем чтение из буфера.
Поэтому я выбрал модель, в которой все метрики собираются раз в N секунд, помещаются в файлы, а затем считываются из файлов по мере необходимости.
Для сбора данных мы будем использовать готовую библиотеку для работы с мостом JMX-HTTP. Библиотека написана на Perl и установлена с использованием CPAN: sudo cpan -i JMX::Jmx4Perl
После успешной установки попробуем получить первые метрики от tomcat с помощью jmx4perl: jmx4perl localhost:8080/jolokia read java.lang:type=Memory HeapMemoryUsage
Вывод команды должен выглядеть примерно так: {
committed => 65470464,
init => 0,
max => 132579328,
used => 10264072
}
Как вы можете догадаться, мы только что получили информацию об использовании памяти Tomcat JVM Heap.
Теперь вам следует написать скрипт для сбора метрик, а затем поместить их в файлы указанного каталога.
Вы можете написать свой собственный или использовать мой пример: #!/usr/bin/perl
use strict;
use warnings;
use Error qw( :try );
use JMX::Jmx4Perl;
use JMX::Jmx4Perl::Alias;
use File::Path qw(make_path remove_tree);
use Data::Dumper;
my %source = (
GC_COPY_COLLECTION_COUNT => ["java. lang:name=Copy,type=GarbageCollector ", "CollectionCount"],
GC_MARK_SWEEP_COLLECTION_COUNT => ["java. lang:name=ConcurrentMarkSweep,type=GarbageCollector ", "CollectionCount"],
GC_COPY_COLLECTION_TIME => ["java. lang:name=Copy,type=GarbageCollector ", "CollectionTime"],
GC_MARK_SWEEP_COLLECTION_TIME => ["java. lang:name=ConcurrentMarkSweep,type=GarbageCollector ", "CollectionTime"],
THREAD_COUNT => ["THREAD_COUNT"],
MEMORY_HEAP_COMITTED => ["MEMORY_HEAP_COMITTED"],
THREAD_COUNT_DAEMON => ["THREAD_COUNT_DAEMON"],
THREAD_COUNT_STARTED => ["THREAD_COUNT_STARTED"],
MEMORY_HEAP_INIT => ["MEMORY_HEAP_INIT"],
RUNTIME_VM_VENDOR => ["RUNTIME_VM_VENDOR"],
MEMORY_HEAP_MAX => ["MEMORY_HEAP_MAX"],
RUNTIME_VM_NAME => ["RUNTIME_VM_NAME"],
CL_TOTAL => ["CL_TOTAL"],
CL_LOADED => ["CL_LOADED"],
CL_UNLOADED => ["CL_UNLOADED"],
THREAD_COUNT_PEAK => ["THREAD_COUNT_PEAK"],
RUNTIME_UPTIME => ["RUNTIME_UPTIME"],
MEMORY_HEAP_USED => ["MEMORY_HEAP_USED"],
RUNTIME_VM_VERSION => ["RUNTIME_VM_VERSION"],
);
my $log_dir = "/var/jmx";
my $result = 0;
my $port = $ARGV[0];
my $cmd = $ARGV[1];
if(defined $cmd && defined $port) {
try {
my $jmx = JMX::Jmx4Perl->new(url => " http://localhost:$port/jolokia/ ");
if($cmd eq "DUMP") {
make_path("$log_dir/$port");
while(my($key, $value) = each %source) {
open FILE, ">$log_dir/$port/$key" or
throw Error::Simple("Could not open file");
print FILE $jmx->get_attribute(@$value) .
"\n"; close FILE; } $result = 1; } else { my $param = $source{$cmd}; $result = $jmx->get_attribute(@$param); } } catch Error with { $result = 0; # --- Uncomment for debug --- #my $ex = shift; #print $ex->{-text}.
"\n"; #print $ex->{-line}.
"\n"; # --- Debug block ended --- }; } else { $result = 0; } print $result .
"\n";
Мы помещаем скрипт в /usr/local/sbin и называем его jmx_grabber. Есть вероятность, что скрипт не сработает. Это связано с первыми четырьмя метриками: GC_COPY_COLLECTION_COUNT, GC_MARK_SWEEP_COLLECTION_COUNT, GC_COPY_COLLECTION_TIME, GC_MARK_SWEEP_COLLECTION_TIME. Метрики отображают не что иное, как статистику сборщика мусора (GC).
Имена сборщиков мусора, используемых в конкретной реализации JVM, могут различаться.
Для JVM HotSpot мне встретились две пары: PS Scavenge + PS MarkSweep и ConcurrentMarkSweep + Copy. Если у вас возникли трудности с определением имени вашего GC, то запустите команду jmx4perl localhost:8080/jolokia attributes | less
а затем найдите ключевое слово «GarbageCollector».
Вы найдете что-то вроде: java.lang:name=ConcurrentMarkSweep,type=GarbageCollector -- CollectionCount = 12
java.lang:name=ConcurrentMarkSweep,type=GarbageCollector -- LastGcInfo =
java.lang:name=ConcurrentMarkSweep,type=GarbageCollector -- CollectionTime = 0
java.lang:name=ConcurrentMarkSweep,type=GarbageCollector -- Name = ConcurrentMarkSweep
java.lang:name=ConcurrentMarkSweep,type=GarbageCollector -- Valid = [true]
Значение «java.lang:name» — это имя одного из «сборщиков мусора».
Теперь напишем bash-скрипт для получения данных из файлов: #!/bin/bash
JMX_DIR="/var/jmx"
if [ -r "$JMX_DIR/$1/$2" ]; then
cat "$JMX_DIR/$1/$2"
else
echo 0;
fi
Для запуска написанных скриптов нам потребуются следующие Perl-библиотеки: File::Path, Module::Find, JSON, Error. Установите их: sudo cpan -i File::Path
sudo cpan -i Module::Find
sudo cpan -i JSON
sudo cpan -i Error
Проверим, все ли было сделано правильно.
Вызовем скрипт со следующими параметрами: /usr/local/sbin/jmx-grabber 8080 RUNTIME_VM_NAME
Нам должна быть возвращена строка «Клиентская виртуальная машина Java HotSpot(TM)».
Теперь создадим папку /var/jmx и вызовем скрипт с другими параметрами: /usr/local/sbin/jmx-grabber 8080 DUMP
Давайте проверим содержимое папки /var/jmx. В нем должен появиться подкаталог 8080, содержащий файлы с метриками JVM, по одному файлу на каждую метрику.
Нетрудно догадаться, что 8080 — это локальный порт, который слушает либо агент jolokia (автономная установка), либо tomcat с контейнером jolokia.
Настроив сбор и чтение метрик, перейдем к процессу их загрузки в Zabbix.
Загрузка метрик JVM в Zabbix
Добавим две строки в файл /etc/zabbix/zabbix_agentd.conf: UserParameter=jmx_grabber[*],/usr/local/sbin/jmx-grabber $1 $2
UserParameter=jmx_reader[*],/usr/local/sbin/jmx-stats-reader $1 $2
После этого не забудьте перезапустить агент zabbix. Добавленные строки позволяют получать доступ к сценариям файловой системы как к обычным метрикам Zabbix. Есть альтернативный способ: можно использовать траппер zabbix, и отправлять статистику в активном режиме без использования агента zabbix. Больших различий нет. При использовании Zabbix-агента периоды сбора данных задаются в Zabbix через пользовательский интерфейс.
Если вы используете траппер, вам придется распространять cron-скрипты для отправки метрик через puppet (или его аналоги).
Теперь пришло время создавать шаблоны.
Я не буду углубляться в этот процесс и прикреплю уже готовый XML-файл шаблона , который необходимо импортировать в Zabbix. Для этого откройте вкладку «Конфигурация -> Экспорт/Импорт» (в последних версиях Zabbix импорт находится в «Конфигурация -> Шаблоны», затем кнопка «Импортировать шаблон») и выберите из списка «Импорт»:
Теперь нам нужно назначить добавленный шаблон нашему серверу.
Перейдите на вкладку «Конфигурация -> Хосты» и нажмите «Сервер Zabbix».
В панели «Связанные шаблоны» добавляем наш шаблон «Template_Multitenant_Tomcat_JMX_Toolkit».
Нажмите «Сохранить», затем перейдите в «Мониторинг -> Последние данные».
Примерно через 20 секунд вы получите первые статистические данные от JVM Tomcat. Если данные не приходят, проверьте, запущен ли zabbix-агент и правильно ли он настроен (см.
выше).
Через полчаса вы можете посмотреть графики («Мониторинг -> Графики»), там для «Tomcat JVM Memory» вы увидите что-то вроде следующего:
Скорее всего, у вас возникнет вопрос, что делать, если на одной физической/виртуальной машине несколько JVM? Ведь в шаблоне явно указан порт 8080. Да, это неприятная особенность, но чтобы добавить для мониторинга несколько JVM одной машины, нужно для каждого порта jolokia создать отдельный шаблон, с которого будут собираться данные.
Проведение испытаний
Хорошо, у нас есть система сбора метрик с помощью Tomcat JVM. Было бы здорово опробовать его в действии.Для этих целей я написал небольшой сервис, создающий потоки, которые, в свою очередь, непрерывно порождают объекты в JVM, пока они не остановятся.
Доступный извне интерфейс управления выглядит следующим образом:
Кнопки «Увеличить» и «Уменьшить» увеличивают и уменьшают количество потоков, а множитель дает контроль над множителем того, как долго поток должен задержаться перед генерацией следующего объекта.
Возможно обслуживание Скачать здесь .
Разместим сервис в Tomcat, а затем проделаем следующие манипуляции:
- увеличьте количество потоков до 20 и подождите 5 минут
- увеличьте количество потоков до 50 и снова подождите 5 минут
- уменьшите множитель задержки потока до 50 и подождите 5 минут
- сбросить количество потоков до нуля
Запкат
Когда я сказал, что не нашел приемлемых готовых решений, я немного соврал.Есть одно решение - это Запкат .
И, кстати, скрещивание с его помощью Tomcat и Zabbix не займет более 5 минут. Почему я изобретал велосипед? Здесь есть две причины:
- zapcat не обновлялся с 2008 года.
Это не то чтобы это плохо - он до сих пор неплохо работает. Но мне не очень хочется использовать систему, которую никто не поддерживает.
- Агент будет подключаться к автономным сервисам zapcat непосредственно в коде приложения.
Для меня это выглядит так, как будто детям при рождении пришивали тонометр и прочие датчики, которые потом можно было удалить только хирургическим путем.
Мне очень не хотелось делать zapcat (который больше не поддерживается) частью приложения.
Это и небезопасно, и с архитектурной точки зрения неграмотно.
Теоретически zapcat можно настроить как javaagent, но готовых реализаций, которые можно подключить с помощью одноименной директивы, я не нашел.
- Хочу ли я интегрировать инструменты мониторинга в свое приложение? (актуально только для отдельных сервисов)
- Хочу ли я делать дополнительную обработку промежуточных данных, которые уже собраны в файловой системе (или кеше).
Возможно, вам захочется вычислить средние итоги по всем экземплярам служб.
- Хочу ли я получить доступ к сервису/приложению через мост jmx, используя инструменты, отличные от zabbix?
Окончательно
Предложенный мною вариант — это не столько готовая система мониторинга, сколько каркас для построения системы мониторинга жизни сервиса исходя из конкретных задач и потребностей.В сочетании с возможностью Zabbix обнаруживать свои агенты и автоматически добавлять сетевые узлы в монитор задача мониторинга работы Java-сервисов существенно упрощается.
Если у вас возникнут трудности с настройкой, пишите в личное сообщение или в комментариях, я помогу вам, чем смогу.
Для тех, кто не хочет вручную настраивать тестовый стенд, предлагаю воспользоваться готовый для VirtualBox (логин красный, пароль пароль).
Приятного экспериментирования и стабильной работы JVM! ;-) P.S.: На сообщения и комментарии могу отвечать только в обед и вечером.
Теги: #jvm #java #zabbix #monitoring #java
-
Защита Конфиденциальности Через Интернет
19 Oct, 24 -
Самые Популярные Базы Данных – 2006–2021 Гг.
19 Oct, 24 -
А1: 2017 – Инъекции (Часть 3 И Последняя)
19 Oct, 24 -
Добрыми Делами Не Прославишься
19 Oct, 24