Cómo conectar de forma remota a JConsole usando JMX

jConsole es una interfaz gráfica que permite monitorizar todo lo que ofrecen las Java Management Extensions (JMX). La Java Virtual Machine ofrece información relacionada con el rendimiento de la Java VM, consumo de recursos y información detallada sobre las aplicaciones que están ejecutandose en ella.

Habilitar JMX en Tomcat

Para habilitar JMX en el servidor de aplicaciones, debemos añadir a la variable de entorno CATALINA_OPTS los siguientes parámetros:

CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote \
-Dcom.sun.management.jmxremote.port=11111 \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false"

Con estos parámetros, cuando reiniciemos Tomcat la JMX levantará en el puerto 11111 y será accesible sin autenticación. Si revisáis la documentación correspondiente podéis ver como establecer autenticación.

Problemas para acceder a jConsole de forma remota

Con esta configuración, observamos que el puerto 11111 escucha por todas las interfaces de red del servidor:

$ netstat -nat | grep LISTEN | grep 11111
 tcp        0      0 :::11111                    :::*                        LISTEN

El problema es que JMX (…y el conector RMI) utilizan dos puertos, uno es el que especificamos en la configuración como puerto remoto JMX, en nuestro caso el 11111 y otro es el que utiliza el conector RMI. Este segundo puerto es dinámico y aleatorio así que la conexión remota con esta configuración no va a funcionar ya que debemos conocer con antelación el puerto para poder conectar.

Cómo acceder de forma remota

Una de las posibilidades es añadir otra directiva a la variable de entorno CATALINA_OPTS. La directiva es «-Djava.rmi.server.hostname» y en ella indicamos la IP a través de la cual se va a acceder remotamente:

-Djava.rmi.server.hostname='192.168.1.100'

Quedaría entonces así, con todos los parámetros aplicados:

CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote \
-Dcom.sun.management.jmxremote.port=11111 \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false"
-Djava.rmi.server.hostname='192.168.1.100'

Sería conveniente en este caso (y en todos, pero en este más) configurar un firewall para restringir el acceso al puerto de JMX.

La otra opción es no activar la IP/hostname de conexión y hacer uso de tuneles SSH, uno estándar y otro de tipo SSH socks tunnel. jConsole tiene soporte para SOCKS así que podemos crear un proxy local SSH SOCKS en un puerto TCP y utilizarlo para conectar a la JMX:

# ssh -D 9999 usuario@192.168.1.100

9999 es el puerto donde levantamos el proxy SOCKS SSH y 192.168.1.100 es el sistema donde está el Tomcat con JMX. Además de este tunel, si estamos detrás de un firewall y el puerto de JMX está bloqueado podemos crear otro tunnel más para mapear el puerto de JMX en localhost:

# ssh -L 11111:localhost:11111 usuario@192.168.1.100

Con estos dos tuneles abiertos ya podemos conectar a JMX con jConsole. La línea de comando que ejecutaríamos es la siguiente:

# jconsole -J-DsocksProxyHost=localhost -J-DsocksProxyPort=9999 \
 service:jmx:rmi:///jndi/rmi://localhost:11111/jmxrmi

Y listo… ya tenemos acceso a jConsole. Hay otras formas de hacer funcionar el acceso remoto pero cara a administradores de sistemas que no controlen demasiado de Java esta es quizás la más sencilla.

jConsole JMX Tomcat