Как получить доступ к Spring -boot JMX удаленно

Я знаю, что spring автоматически выставляет JMX beans. Я смог получить доступ к нему локально с помощью VisualVM.

Однако на prod, как я могу подключиться к удаленному приложению, используя его JMX beans? Есть ли порт по умолчанию, или я должен что-то определить дополнительно?

Спасибо, лучей.

Ответы

Ответ 1

По умолчанию JMX автоматически доступен локально, поэтому запуск jconsole локально обнаруживает все ваши локальные приложения Java без воздействия порта.

Чтобы получить доступ к приложению через JMX удаленно, вы должны указать порт реестра RMI. Дело в том, что при подключении JMX инициализирует этот порт и , а затем устанавливает соединение с данными на случайном высоком порту, что является огромной проблемой, если у вас есть межсетевой экран посередине. ( "Эй, сидэдмины, просто откройте все, mkay?" ).

Чтобы заставить JMX подключиться обратно к тому же порту, который вы установили, у вас есть несколько вариантов:

Вариант 1: Командная строка

-Dcom.sun.management.jmxremote.port=$JMX_REGISTRY_PORT 
-Dcom.sun.management.jmxremote.rmi.port=$RMI_SERVER_PORT

Если вы используете Spring Boot, вы можете поместить это в свой (appname).conf файл, который живет рядом с развертыванием (appname).jar.

Вариант 2: Конфигурация Tomcat/Tomee

Настроить JmxRemoteLifecycleListener:

Maven Jar:

    <dependency>
        <groupId>org.apache.tomcat</groupId>
        <artifactId>tomcat-catalina-jmx-remote</artifactId>
        <version>8.5.9</version>
        <type>jar</type>
    </dependency>

Настройте свой server.xml:

<Listener className="org.apache.catalina.mbeans.JmxRemoteLifecycleListener"
      rmiRegistryPortPlatform="10001" rmiServerPortPlatform="10002" />

Вариант 3: настроить программно

@Configuration
public class ConfigureRMI {

    @Value("${jmx.rmi.host:localhost}")
    private String rmiHost;

    @Value("${jmx.rmi.port:1099}")
    private Integer rmiPort;

    @Bean
    public RmiRegistryFactoryBean rmiRegistry() {
        final RmiRegistryFactoryBean rmiRegistryFactoryBean = new RmiRegistryFactoryBean();
        rmiRegistryFactoryBean.setPort(rmiPort);
        rmiRegistryFactoryBean.setAlwaysCreate(true);
        return rmiRegistryFactoryBean;
    }

    @Bean
    @DependsOn("rmiRegistry")
    public ConnectorServerFactoryBean connectorServerFactoryBean() throws Exception {
        final ConnectorServerFactoryBean connectorServerFactoryBean = new ConnectorServerFactoryBean();
        connectorServerFactoryBean.setObjectName("connector:name=rmi");
        connectorServerFactoryBean.setServiceUrl(String.format("service:jmx:rmi://%s:%s/jndi/rmi://%s:%s/jmxrmi", rmiHost, rmiPort, rmiHost, rmiPort));
        return connectorServerFactoryBean;
    }
}

Трюк, вы увидите, это serviceUrl, в котором вы указываете как хост/порт jmx: rmi, так и хост/порт jndi: rmi. Если вы укажете оба варианта, вы не получите случайную высокую "проблему".

Ответ 2

Добавьте следующие JVM-свойства в "$ JAVA_OPTS" (в вашем приложении):

-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=<PORT_NUMBER> -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=<HOST'S_IP>

В Jconsole/Visual VM для подключения:

service:jmx:rmi:///jndi/rmi://<HOST'S_IP>:<PORT_NUMBER>/jmxrmi

Он не включает безопасность, но поможет вам подключиться к удаленному серверу.

Ответ 3

Проверенный подход на Java 1.8.0_71 и Spring Boot (1.3.3.RELEASE). Добавьте параметры к аргументам JVM для контролируемой JVM.

-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=12348 -Dcom.sun.management.jmxremote.authenticate=true -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.rmi.port=12349 -Dcom.sun.management.jmxremote.password.file=/somewhere/jmxremote.password -Dcom.sun.management.jmxremote.access.file=/somewhere/jmx/jmxremote.access

com.sun.management.jmxremote.port используется для определения фиксированного порта реестра RMI, а com.sun.management.jmxremote.rmi.port используется для указания JVM использовать фиксированный порт RMI, но НЕ использовать случайный.

Установив это, я могу подключить JVM-клиент от удаленного хоста к контролируемой JVM через брандмауэр, только открывая порты 12348 и 12349.

Я тестировал с помощью java -jar cmdline-jmxclient-0.10.3.jar user:pwd hostip:12348 на удаленном компьютере, который генерирует ниже результата (сокращенно только для демонстрации).

java.lang:type=Runtime
java.lang:name=PS Scavenge,type=GarbageCollector
Tomcat:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/,j2eeType=Filter,name=requestContextFilter
java.nio:name=mapped,type=BufferPool
Tomcat:host=localhost,type=Host
java.lang:name=Compressed Class Space,type=MemoryPool
.......

Бак загружается из Здесь.

Ответ 4

Да, если вы работаете в Linux, тогда вам нужно настроить порт в IPtables, порт, который принадлежит JMX.
Также вам нужно также настроить IP-адрес на клиентском m/c, чтобы доступ к нему мог получить только ваш м/c.