Непрерывный Мониторинг Jvm С Помощью Zabbix

Допустим, у вас есть большое приложение, написанное на 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. Необходимо организовать сбор данных.

Схема сбора данных будет выглядеть так:

Непрерывный мониторинг JVM с помощью Zabbix

Объясню, почему я не собираю метрики напрямую, а использую промежуточный буфер.

Если настроить схему без него, то при каждом запросе будет запускаться скрипт сбора статистики 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 импорт находится в «Конфигурация -> Шаблоны», затем кнопка «Импортировать шаблон») и выберите из списка «Импорт»:

Непрерывный мониторинг JVM с помощью Zabbix

Теперь нам нужно назначить добавленный шаблон нашему серверу.

Перейдите на вкладку «Конфигурация -> Хосты» и нажмите «Сервер Zabbix».

В панели «Связанные шаблоны» добавляем наш шаблон «Template_Multitenant_Tomcat_JMX_Toolkit».

Нажмите «Сохранить», затем перейдите в «Мониторинг -> Последние данные».

Примерно через 20 секунд вы получите первые статистические данные от JVM Tomcat. Если данные не приходят, проверьте, запущен ли zabbix-агент и правильно ли он настроен (см.

выше).

Через полчаса вы можете посмотреть графики («Мониторинг -> Графики»), там для «Tomcat JVM Memory» вы увидите что-то вроде следующего:

Непрерывный мониторинг JVM с помощью Zabbix

Скорее всего, у вас возникнет вопрос, что делать, если на одной физической/виртуальной машине несколько JVM? Ведь в шаблоне явно указан порт 8080. Да, это неприятная особенность, но чтобы добавить для мониторинга несколько JVM одной машины, нужно для каждого порта jolokia создать отдельный шаблон, с которого будут собираться данные.



Проведение испытаний
Хорошо, у нас есть система сбора метрик с помощью Tomcat JVM. Было бы здорово опробовать его в действии.

Для этих целей я написал небольшой сервис, создающий потоки, которые, в свою очередь, непрерывно порождают объекты в JVM, пока они не остановятся.

Доступный извне интерфейс управления выглядит следующим образом:

Непрерывный мониторинг JVM с помощью Zabbix

Кнопки «Увеличить» и «Уменьшить» увеличивают и уменьшают количество потоков, а множитель дает контроль над множителем того, как долго поток должен задержаться перед генерацией следующего объекта.

Возможно обслуживание Скачать здесь .

Разместим сервис в Tomcat, а затем проделаем следующие манипуляции:

  • увеличьте количество потоков до 20 и подождите 5 минут
  • увеличьте количество потоков до 50 и снова подождите 5 минут
  • уменьшите множитель задержки потока до 50 и подождите 5 минут
  • сбросить количество потоков до нуля
В результате мы получим следующие графики:

Непрерывный мониторинг JVM с помощью Zabbix



Непрерывный мониторинг JVM с помощью Zabbix



Непрерывный мониторинг JVM с помощью Zabbix



Запкат
Когда я сказал, что не нашел приемлемых готовых решений, я немного соврал.

Есть одно решение - это Запкат .

И, кстати, скрещивание с его помощью Tomcat и Zabbix не займет более 5 минут. Почему я изобретал велосипед? Здесь есть две причины:

  • zapcat не обновлялся с 2008 года.

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

  • Агент будет подключаться к автономным сервисам zapcat непосредственно в коде приложения.

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

    Мне очень не хотелось делать zapcat (который больше не поддерживается) частью приложения.

    Это и небезопасно, и с архитектурной точки зрения неграмотно.

    Теоретически zapcat можно настроить как javaagent, но готовых реализаций, которые можно подключить с помощью одноименной директивы, я не нашел.

Чтобы решить, нужен ли вам описанный мной метод мониторинга или zapcat подойдет в качестве простой в развертывании альтернативы, задайте себе следующие вопросы:
  • Хочу ли я интегрировать инструменты мониторинга в свое приложение? (актуально только для отдельных сервисов)
  • Хочу ли я делать дополнительную обработку промежуточных данных, которые уже собраны в файловой системе (или кеше).

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

  • Хочу ли я получить доступ к сервису/приложению через мост jmx, используя инструменты, отличные от zabbix?


Окончательно

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

В сочетании с возможностью Zabbix обнаруживать свои агенты и автоматически добавлять сетевые узлы в монитор задача мониторинга работы Java-сервисов существенно упрощается.

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

Для тех, кто не хочет вручную настраивать тестовый стенд, предлагаю воспользоваться готовый для VirtualBox (логин красный, пароль пароль).

Приятного экспериментирования и стабильной работы JVM! ;-) P.S.: На сообщения и комментарии могу отвечать только в обед и вечером.

Теги: #jvm #java #zabbix #monitoring #java

Вместе с данным постом часто просматривают: