Технология JMX
Наверно самое важное в понимании JMX – понять цель ее создания. Технология JMX была разработана для упрощения разработки систем мониторинга и управления. Причем управлять можно фактически чем угодно – лишь бы это было написано на Java. Это может быть микро-устройство типа считывателя отпечатка или система, включающая тысячи машин, каждая из которых предоставляет определенные сервисы.
Типичные варианты использования технологии JMX:
— просмотр и изменение конфигурации приложения
— сбор и публикация статистических данных о рабте приложения
— извещение о каких-либо неверных изменениях состояния
Что очень важно отметить — JMX по сути приказывает разработчику рассматривать ресурсы приложения как объекты и работать с ними как с управляемыми ресурсами в распределенной среде объектов.
Какие выгоды предлагает JMX ? Вот как эти выгоды описывает Sun:
- Простота реализации. Архитектура JMX основана на понятии «сервера управляемых объектов» который выступает как управляющий агент и может быть запущен на многих устройствах/компьютерах, которые поддерживают JAVA.
- Масштабируемость. Службы агентов JXM являются независимыми и могут быть встроены наподобие plug-in’ов в агента JMX. Компонентно-основанаая система позволяет создавать масштабируемые решения от крохотных устройств до очень крупных систем.
- Возможность расширять концепцию в будущем. JMX позволяет создавать гибкие решения. Например, JMX позволяет создавать удобные решения, которые могут находить различные сервисы.
- Концентрация на управлении. JMX предоставляет сервися, разработанные для работы в распределенных средах и его API спроектировано для решений, которые управляют приложениями, сетями, сервисами и т.д.
JMX позволяет создавать многоуровневую архитектуру, где управляемые ресурсы и управляющее приложение могут быть встроены в одно решение, как показано на рисунке. Ресурсы представляют из себя Java-обхекты – ManagedBeans (MBeans), которые регистрируются на основном сервере –MBean-server. Этот сервер действует как агент и может быть запущен практически везде, где есть JVM.
Давайте подробнее разберем то, что изображено на рисунке.
Instrumentation Level
Этот слой содержит MBean’ы и ресурсы, которыми они управляют. Ресурсы могут быть управляемы, если они либо разработаны на Java, либо имеют какую-нибудь Java-обертку. По сути ресурс становится объектом типа MBean (стандартным или динамическим – об этом немного позже). СтандартныеMBeans это Java-объекты, которые подчиняются определенным образцам проектирования (например они должны иметь конструктор и сеттеры и геттеры). Динамические MBeans разрабатываются согласно определенному интерфейсу, который предоставляет большую гибкость при исполнении. Уровень инструментария позволяет MBean’ам быть управляемыми на уровне агента (Agent Level), однако на данном уровне разработчику не надо знать о том, как устроен агент с которым им придется взаимодействовать.
Основными компонентами Instrumenation Level являются:
- MBeans – это Java-объекты, которые реализуют определенный интерфейс. Интерфейс включает: 1) некие величины, которые могут быть доступны; 2) операции, которые могут быть вызваны; 3) извещения, которые могут быть посланы; 4) конструкторы.
Существует 4 типа MBeans:
1. Standard MBeans. Самые простые бины. Их управляющий интерфейс определяется набором методов
2. Dynamic MBeans. Они реализуют специализированный интерфейс, который делают доступным во время исполнения.
3. Open MBeans. Это Dynamic MBeans, которые используют только основные типы данных для универсального управления.
4. Model MBeans. Это Dynamic MBeans, которые полностью конфигурируемы и могут показать свое описание во время исполнения (нечто вродеReflection)
- Notification Model – JMX определяет базовую модель нотификаторов, которая основана на Java событиях (event). Используя нотификацию MBeansи JMX агенты могут пересылать необходимую информацию между собой
- MBean Metadata Classes – Эти классы содержат структуры для описания всех компонентов MBeans интерфейсов: атрибуты, нотификаторы, операции, конструкторы. Для каждого из них метаданные включают имя, описание и определенные характеристики (например атрибут только для чтения или для чтения/записи и т.д).
Agent Level
Этот слой включает JMX агента, который используется для «опубликования» и «запуска» MBeans. Другими словами именно агент является средой внутри которой могут исполнятся MBeans. Агент соответствует спецификации для агентов JMX, управляет ресурсами и делает их доступными для удаленного управления. Обычно агент располагается на той же машине, где установлены ресурсы, которыми он управляет, но это не является обязательным. Агент включает в себя следующие компоненты:
- MBean Server – это реестр объектов, которые используются для управления. Любой объект зарегистрированный на сервере становится доступным для приложений. Надо отметить, что сервер публикует только интерфейсы и не дает прямых ссылок на объекты. Любые ресурсы, которыми вы хотите управлять должны быть зарегистрированы на сервере как MBean. Сервер предоставляет стандратный интерфейс для доступа к MBean. Интересно, что регистрировать MBean может любой другой MBean, сам агент или удаленное приложение через рапределенные сервисы. Когда вы регистрируете MBean вы должны дать ему уникальное имя, которое будет использовано для обращения к даному объекту.
- Службы агента – объекты которые могут взаимодействовать с ресурсами в MBean (используются MBean для обращения к ресурсам). Для управления разработан JMX API, который включает в себя следующие сервисы:
1. Dynamic Class Loader – с помощью management applet’а (m-let) позволяет загружать классы и двоичные библиотеки из различных мест
2. Мониторы – они наблюдают за изменениями величин (чиловых или строковых) MBean и могут извещать об этих изменениях другие объекты.
3. Таймеры – обеспечивают нотификацию по расписанию.
4. Другие сервисы – определяют отношения между MBean на предопределенных типах
Manager Level
Этот слой содержит компоненты, которые позволяют приложениям взаимодействовать с агентом. Он обеспечивает интерфейс для реализации JMXменеджеров.
JMX и Java SE 5.0
Начиная с Java SE 5 сделана поддержка JMX 1.2 и JMX remote API 1.0 которые являются на сегодня официальной реализацией. Java SE включает в себя следующие подсистемы:
- Инструментарий JVM – разработан для мониторинга и управления. Является встроенной возможностью для локального и удаленного доступа.
- API мониторинга и управления – пакет java.kang.management включает интерфейс для мониторинга и управления JVM. С помощью него можно получать различную информацию – количество загруженных классов, количество потоков, параметры памяти, статистику сборщика мусора и другое.
- Management tools – различные утилиты. В частности JConsole с помощью которой можно подключиться к работающей JVM и получить ее параметры.
Вы можете сами посмотреть параметры запущенной JVM с помощью утилиты JConsole. Можно сделать это локально – просто запустите какое-нибудь приложение (лучше пусть это будет форма на экране – чтобы не закрывалась) и потом запустите jconsole – прямо из командной строки. Если у вас не прописан путь до какталога с этой утилитой (она находится в кактлоге с javac), то поискать его в этом каталоге.
Удаленно несколько сложнее – чтобы не мучатся с настройками файла паролей приложение можно запустить такой строкой
1 2 3 4 5 |
java -Dcom.sun.management.jmxremote.port=10999 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -cp . MainClass |
И потом набираем
1 |
jconsole localhost:10999 |
Можно будет увидеть достаточно много всякой информации. Походите по закладкам, посмотрите – может что и увидите интересное.
Вот для примера список тредов – я выделил тред, который отвечает за удаленный мониторинг.
А теперь давайте напишем первый и очень простой MBean. Для этого сначала описывается интерфейс и класс, который рего реализует. Мы сделаем очень простые интерфейс и класс.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
public interface HelloMBean { public void setMessage(String message); public String getMessage(); public void sayHello(); } public class Hello implements HelloMBean { private String message = null; public Hello() { message = "Hello there"; } public Hello(String message) { this.message = message; } public void setMessage(String message) { this.message = message; } public String getMessage() { return message; } public void sayHello() { System.out.println(message); } } |
Как видите здесь все очень просто – интерфейс описывает всего три метода. Сеттер и геттер для строки и одно действие – «скажи Hello» — sayHello.
Класс тоже не представляет особых сложностей. Он имеет два конструктора – один с инициализацией строки по умолчанию и второй уже с указанной строкой. Также реализуются все три метода. Но тем не менее это уже может быть самым настоящим MBean’ом. Так что гордитесь.
Если отнестись более серьезно, то на самом деле это сильный шаг к объектному пониманию JMX. Ведь у нас есть появляется легко делать сразу несколько вещей:
- Устанавливать или считывать параметры. (Я говорю о методах set/get). Сейчас там просто строка, но ведь может быть реально ценное значение. Например свободное место на диске. Правда он скорее всего будет ReadOnly. Но может быть и управляемые параметры – например количество подключаемых пользователей. Или системное время. Или новый URL к базе данных для статистики.
- Просить выполнить MBean какое-либо действие (я о sayHello сейчас) – например перезапустить приложение. Или отправить почту. Да мало ли всяких полезных вещей можно попросить.
Само собой просто так наши MBean работать не будет. Ему нужен сервер, на котором он будет работать. Давайте перейдем к нему.
Локальная версия
В этом разделе мы создадим сервер и сделаем его локальным, т.е. он будет доступен только на нашей машине и с нашей машины. По сути напрямую.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
import javax.management.*; import java.lang.management.*; public class SimpleAgent { private MBeanServer mbs = null; public SimpleAgent() { // Получить экземпляр MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); // Создаем наш MBean Hello helloBean = new Hello(); ObjectName helloName = null; try { // И регистрируем его на платформе MBeanServer helloName = new ObjectName("SimpleAgent:name=hellothere"); mbs.registerMBean(helloBean, helloName); } catch(Exception e) { e.printStackTrace(); } } // Это вспомогательный метод – он позволяет нашей программе // остановиться и ждать private static void waitForEnterPressed() { try { System.out.println("Press to continue..."); System.in.read(); } catch (Exception e) { e.printStackTrace(); } } public static void main(String argv[]) { SimpleAgent agent = new SimpleAgent(); System.out.println("SimpleAgent is running..."); SimpleAgent.waitForEnterPressed(); } } |
Самое главное в нашей программе – это строки
1 |
mbs = ManagementFactory.getPlatformMBeanServer(); |
и
1 |
mbs.registerMBean(helloBean, helloName); |
Все остальное вспомогательное. Первая строка возвращает нам экземпляр класса, коорый реализует интерфейс MBeanServer. Этот интерфейс содержит немалое число методов для управления MBean’ами, которые на нем зарегистрированы. Я вам советую посмотреть описание в API – много интересного найдете.
А вторая строка регистрирует наш замечательный MBean. И теперь к нему можно будет обращаться. Давайте сделаем это.
Создаем три файла в какой-нибудь директории с вышепреведенным кодом. Собираем его с помощью команды
javac *.java
1 |
javac *.java |
Получим три файла – Hello.class, HelloMBean.class, SimpleAgent.class. Теперь можно запускать
1 |
java –cp . -Dcom.sun.management.jmxremote SimpleAgent |
Видим на экране сообщение:
SimpleAgent is running…
Press to continue…
Наш сервер с нашим бином запущен и теперь мы можем к нему обратиться. Не закрывайте это окошко – оно нам еще пригодится. Запускаем уже известную утилиту jconsole
Видим наше приложение. Выделяем и жмем «Connect».
Я выделил самое интересное – закладку, где можно посмотреть MBean, к которым можно обратиться. Я уже изменил наше значение «Hello there» на «Hi,world». Сделать это не просто, а очень просто – исправляйте прямо в строке
А теперь в дереве слева выделим пункт ‘Operations” – “sayHello”.
Если мы нажмем кнопку с надписью “sayHello”, то увидим сообщение
И посмотрим на окно, где работает наш сервер. Вы наверняка увидите там надпись «Hi, world» (Если у вас такая же надпись как и у меня).
Удаленный вызов через RMI
Для удаленного вызова нам потребуется как минимум Java 5.0. В принципе можно и 1.4, но тогда надо будет устанавливать дополнительные пакеты. Так что для скорости будем работать на Java 5.0 или выше.
Идея удаленного доступа основана на адаптерах (коннекторах), через которые приложения на Manager Level (см. выше) могут взаимодействовать с агентом (MBeanServer). Другими словами сам MBeanServer может подключать различные коннекторы, через которые он становится доступен. Мы рассмотрим два варината подключения – через RMI и через HTTP.
RMI коннектор
Код нашего сервера несколько изменится.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
import javax.management.*; import java.lang.management.*; import javax.management.remote.*; public class SimpleAgent { private MBeanServer mbs = null; public SimpleAgent() { // Получить экземпляр MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); HtmlAdaptorServer adapter = new HtmlAdaptorServer(); // Создаем наш MBean Hello helloBean = new Hello(); ObjectName helloName = null; try { // И регистрируем его на платформе MBeanServer helloName = new ObjectName("SimpleAgent:name=hellothere"); mbs.registerMBean(helloBean, helloName); // Здесь мы создаем RMI connector – скопируйте URL, он нам пригодится JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:9999/server"); JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs); cs.start(); } catch(Exception e) { e.printStackTrace(); } } // Это вспомогательный метод - он позволяет нашей программе // остановиться и ждать private static void waitForEnterPressed() { try { System.out.println("Press to continue..."); System.in.read(); } catch (Exception e) { e.printStackTrace(); } } public static void main(String argv[]) { SimpleAgent agent = new SimpleAgent(); System.out.println("SimpleAgent is running..."); SimpleAgent.waitForEnterPressed(); } } |
Теперь мы можем собрать наш новый класс.
1 |
javac *.java |
Но теперь он не просто должен быть запущен – он должен подсоедениться к репозитарию RMI и пользователи смогут через этот репозитарий смотреть, что происходит с нашими MBean’ами.
Репозитарий на самом деле запускается очень просто
1 |
rmiregistry 9999 |
На что следует обратить внимание при запуске rmiregistry. Я несколько часов возился с этой проблемой, пока случайно не обнаружил решение. В случае если у вас установлено несколько версий Java, то вы должны использовать ТОЛЬКО ОДНУ для всех операций – компиляция, запускrmiregistry (именно из той же версии JDK) и запуск вашего приложения.
После запуска репозитория запускаем наше приложение.
1 |
java –cp . SimpleAgent |
Если никаких проблем не увидели, то можем запускать jconsole. В этот раз мы выберем не локальное подключение, а удаленное. Скопируйте строку
1 |
service:jmx:rmi:///jndi/rmi://localhost:9999/server |
и подставьте ее в строку для “Remote Process” (как показано на рисунке)
В общем-то и все. Теперь вы «зашли» удаленно на свой сервер. И опять же можете управлять им без проблем.
HTTP коннектор
И теперь мы попробуем использовать коннектор HTTP. Для этого нам все-таки придется скачать дополнтельный пакет с сайта Sun Mycrosystems.
Зайдите по ссылке — Java Management[tm] Extensions (JMX) Download Information
Там надо будет скачать пакет JMX 1.2.1 Reference Implementation. Вы получите файл jmx-1_2_1-ri.zip. Распакуйте его в какую-нибудь директорию – нам потребуется оттуда пакет jmxtools.jar. Скопируйте его прямо в директорию с нашими классами- так будет удобнее.
И теперь код нашего сервера. Теперь он регистрирует у себя HTTP коннектор
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
import javax.management.*; import java.lang.management.*; import com.sun.jdmk.comm.HtmlAdaptorServer; public class SimpleAgent { private MBeanServer mbs = null; public SimpleAgent() { // Получить экземпляр MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); HtmlAdaptorServer adapter = new HtmlAdaptorServer(); // Создаем наш MBean Hello helloBean = new Hello(); ObjectName adapterName = null; ObjectName helloName = null; try { // И регистрируем его на платформе MBeanServer helloName = new ObjectName("SimpleAgent:name=hellothere"); mbs.registerMBean(helloBean, helloName); // Теперь мы регистрируем коннектор, который // будет доступен по HTTP-протоколу adapterName = new ObjectName("SimpleAgent:name=htmladapter,port=8000"); adapter.setPort(8000); mbs.registerMBean(adapter, adapterName); adapter.start(); } catch(Exception e) { e.printStackTrace(); } } // Это вспомогательный метод - он позволяет нашей программе // остановиться и ждать private static void waitForEnterPressed() { try { System.out.println("Press to continue..."); System.in.read(); } catch (Exception e) { e.printStackTrace(); } } public static void main(String argv[]) { SimpleAgent agent = new SimpleAgent(); System.out.println("SimpleAgent is running..."); SimpleAgent.waitForEnterPressed(); } } |
Для сборки теперь надо будет набрать вот такую команду
1 |
javac –cp jmxtools.jar *.java |
Для запуска команда тоже немного изменится. Не забудьте отключить rmiregistry – он нам здесь не понадобится.
1 |
java –cp .;jmxtools.jar SimpleAgent |
Если ничего не напутали, то снова наш егант запустится как обычно. И теперь вы можете его использовать набрав URL в броузере.
http://localhost:8000
На страничке можно будет увидеть наш замечательный MBean
Нажмите на верхнюю из отмеченных ссылок и вы попадете на страницу, которая позволит вам работать с вашим бином.
Думаю, что разобраться будет несложно.
В этой статье я не рассматривал возможности написнаия клиентских приложений. Хотя конечно же и можно и нужно будет писать, если вы захотите. Но об этом мы поговорим в другой раз.
Наверно на сегодня это все, что я хотел бы рассказать про технологию JMX. Все Ваши комментарии и замечания будут приняты с благодарностью.