Содержание

понедельник, 25 апреля 2011 г.

Пять способов настроить доступ к JMX для приложения за firewall

Самый распространенный доступ к JMX с удаленной машины - это RMI, который использует рэндомные порты, что, как известно, недопустимо при работе с firewall. Таким образом, если вы планируете разместить свое приложение в DMZ, то подумайте заранее, как вы будете решать данную проблему. В данном топике я приведу несколько способов решения, и вам останется только выбрать то, что для вас подойдет наилучшим образом.

RMI

Для работы JMX через RMI необходимо два порта. Первый - java registry, фиксированный порт, который используется для обнаружения удаленного сервиса. Второй - порт по которому вы будете общаться с обнаруженным сервисом, по-умолчанию назначается произвольным образом, что для работы за firewall недопустимо. На самом деле никакой проблемы тут нет, так как, на самом деле, RMI позволяет фиксировать данный порт. Единственно вам придется программно стартовать JMXConnector, т.к. стандартным подходом с указанием параметров JVM тут не обойтись. Как это сделать в деталях описано тут, но я все же приведу небольшой кусок кода.
Кстати, для registry и RMI сервиса можно использовать один и тот же порт.

HTTP Adapter

Другой, способ решения проблемы с произвольным портом RMI - это использование другого протокола доступа к JMX на удаленной машине. HTTP в случае с firewall подойдет как нельзя лучше. Есть стандартная библиотечка от Sun Oracle, правда она не идет вместе с JDK. Подробную инструкцию, как ей пользоваться, можно найти тут, но я здесь тоже приведу кусочек кода, как все это запустить.
Теперь вы сможете работать с JMX в своем браузере по HTTP: http://localhost:8000.

Spring

Если ваше приложение активно использует Spring, то подход в этом случае не меняется, просто программное указание фиксированного порта для RMI выглядит немного по-другому:

Tomcat

Разработчики Tomcat об этой проблеме знали и предусмотрели её решение с помощью специального listener прямо в конфигурационном файле server.xml

Когда приложений очень много

Таким образом мы видим, что для доступа к JMX нам необходимо зафиксировать и открыть в firewall один-два порта. Если же у нас приложений много, то это может стать немалой головной болью. Решить данную проблему более-менее элегантно у меня не получилось. Но все же кое-какие наметки у меня есть.

Можно иметь одно приложение с открытым портом и через него него ходить во все остальные. Для этого нужно сделать форвардинг всех JMX сообщений с этого приложения на то, которое нас действительно интересует. Как это сделать можно почитать тут. Там правда описана прокси из RMI/JRMP протокола в RMI/OOIP, но идея та же самая. В приложении находящемся в DMZ создается MBeanServerConnection к любой другой машине в DMZ и все вызовы к нему проксируются через фиксированный порт. Единственное, что надо доделать, это переключать прокси к разным приложениям, для чего, впрочем, можно заэкспоузить тот же JMX bean. Не очень элегантно, довольно медленно, но зато вы имеете стандартный доступ к JMX через JConsole с одной-единственной дыркой в firewall.