Saltar al contenido

Cómo acceder a Spring-boot JMX de forma remota

Solución:

De forma predeterminada, se puede acceder a JMX de forma local de forma automática, por lo que ejecutar jconsole en la zona detectaría todas sus aplicaciones Java locales sin exposición de puertos.

Para acceder a una aplicación a través de JMX remotamente debe especificar un puerto de registro RMI. Lo que debe saber es que cuando se conecta, JMX se inicializa en ese puerto y luego establece una conexión de datos en un alto aleatorio puerto, que es un gran problema si tiene un firewall en el medio. (“Hola, administradores de sistemas, abran todo, ¿verdad?”).

Para obligar a JMX a volver a conectarse en el mismo puerto que ha establecido, tiene un par de las siguientes opciones. Nota: puede usar diferentes puertos para JMX y RMI o puede usar el mismo puerto.

Opción 1: línea de comandos

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

Si está utilizando Spring Boot, puede poner esto en su (appname).conf archivo que vive junto a tu (appname).jar despliegue.

Opción 2: configuración de Tomcat / Tomee

Configure un JmxRemoteLifecycleListener:

Tarro de Maven:

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

Configure su server.xml:

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

Opción 3: configurar programáticamente

@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;
    }
}

El truco, verás, es el serviceUrl en el que especifica tanto el host / puerto jmx: rmi como el host / puerto jndi: rmi. Si especifica ambos, no obtendrá el “problema” alto aleatorio.

Editar: Para que funcione la comunicación remota JMX, deberá tomar una decisión sobre la autenticación. Es mejor hacerlo en 3 pasos distintos: 1) configuración básica con -Dcom.sun.management.jmxremote.authenticate=false luego 2) agregue un archivo de contraseña (-Dcom.sun.management.jmxremote.password.file). Consulte aquí las instrucciones. + -Dcom.sun.management.jmxremote.ssl=false y luego 3) configurar SSL.

Agregue las siguientes propiedades de JVM en “$ JAVA_OPTS” (en su aplicación):

-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>

En Jconsole / Visual VM, use lo siguiente para conectarse:

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

No habilita la seguridad, pero le ayudará a conectarse al servidor remoto.

Un enfoque probado en Java 1.8.0_71 y Spring Boot (1.3.3.RELEASE). Añada los siguientes parámetros a los argumentos de la JVM para la JVM supervisada.

-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

los com.sun.management.jmxremote.port se utiliza para definir el puerto de registro RMI fijo, y el com.sun.management.jmxremote.rmi.port se utiliza para indicar a JVM que utilice un puerto RMI fijo, pero NO utilice uno aleatorio.

Al configurar esto, puedo conectar el cliente JVM desde el host remoto a la JVM monitoreada a través de un firewall que acaba de abrir los puertos 12348 y 12349.

Probé usando java -jar cmdline-jmxclient-0.10.3.jar user:pwd hostip:12348 en una máquina remota, que genera la siguiente salida (abreviada solo para demostración).

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
.......

El frasco se descarga desde aquí.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *