¿Alguien ha conseguido que funcione una JConsole JMX remota?


120

Parece que nunca he conseguido que esto funcione en el pasado. Actualmente, SÉ que no funciona.

Pero iniciamos nuestro proceso de Java:

-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=6002
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false

Puedo hacer telnet al puerto, y "hay algo allí" (es decir, si no inicio el proceso, nada responde, pero si lo hago, lo hace), pero no puedo hacer que JConsole funcione completando la IP y puerto.

Parece que debería ser tan simple, pero sin errores, sin ruido, sin nada. Simplemente no funciona.

¿Alguien sabe el consejo para esto?


3
Si está utilizando Tomcat, esta puede ser la solución: stackoverflow.com/questions/1263991/…
Hajo Thelen

5
¿Olvidaste aceptar algo aquí @Will?
Gray

Respuestas:


126

Tengo una solución para esto:

Si su proceso Java se está ejecutando en Linux detrás de un firewall y desea iniciar JConsole / Java VisualVM / Java Mission Control en Windows en su máquina local para conectarlo al puerto JMX de su proceso Java .

Necesita acceder a su máquina Linux a través del inicio de sesión SSH. Toda la comunicación se canalizará a través de la conexión SSH.

SUGERENCIA: esta solución funciona sin importar si hay un firewall o no.

Desventaja: cada vez que reinicie su proceso de Java, deberá realizar todos los pasos del 4 al 9 nuevamente.


1. Necesita putty-suite para su máquina Windows desde aquí:

http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html

Al menos el putty.exe


2. Defina un puerto libre en su máquina Linux:

<jmx-remote-port>

Ejemplo:

jmx-remote-port = 15666      


3. Agregue argumentos al proceso java en la máquina Linux

Esto debe hacerse exactamente así. Si se hace como se muestra a continuación, funciona para máquinas Linux detrás de cortafuegos (funciona debido al -Djava.rmi.server.hostname=localhostargumento).

-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=<jmx-remote-port>
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.local.only=false
-Djava.rmi.server.hostname=localhost

Ejemplo:

java -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=15666 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.local.only=false -Djava.rmi.server.hostname=localhost ch.sushicutta.jmxremote.Main


4. Obtenga el Id. De proceso de su proceso Java

ps -ef | grep <java-processname>

result ---> <process-id>

Ejemplo:

ps -ef | grep ch.sushicutta.jmxremote.Main

result ---> 24321


5. Busque un puerto arbitrario para la descarga de stubs de RMIServer

El proceso de java abre un nuevo puerto TCP en la máquina Linux, donde RMI Server-Stubs estará disponible para descargar. Este puerto también debe estar disponible a través de SSH Tunnel para obtener una conexión a la máquina virtual Java.

Con netstat -lpeste puerto también se pueden encontrar lsof -ipistas sobre qué puerto se ha abierto desde el proceso java.

NOTA: Este puerto siempre cambia cuando se inicia el proceso de Java.

netstat -lp | grep <process-id>

tcp        0      0 *:<jmx-remote-port>     *:*     LISTEN      24321/java
tcp        0      0 *:<rmi-server-port>     *:*     LISTEN      24321/java


result ---> <rmi-server-port>

Ejemplo:

netstat -lp | grep 24321

tcp        0      0 *:15666     *:*     LISTEN      24321/java
tcp        0      0 *:37123     *:*     LISTEN      24321/java


result ---> 37123


6. Habilite dos túneles SSH desde su máquina Windows con masilla

Source port: <jmx-remote-port>
Destination: localhost:<jmx-remote-port>
[x] Local       
[x] Auto       

Source port: <rmi-server-port>
Destination: localhost:<rmi-server-port>
[x] Local       
[x] Auto

Ejemplo:

Source port: 15666
Destination: localhost:15666
[x] Local       
[x] Auto       

Source port: 37123
Destination: localhost:37123
[x] Local       
[x] Auto


Configuración para abrir un túnel SSL a través de Putty


7. Inicie sesión en su máquina Linux con Putty con este SSH-Tunnel habilitado.

Deje abierta la sesión de masilla.

Cuando haya iniciado sesión, Putty conectará todas las conexiones TCP a la máquina Linux a través del puerto SSH 22.

Puerto JMX:

Windows machine: localhost:15666   >>> SSH >>>   linux machine: localhost:15666

RMIServer-Stub-Port:

Windows Machine: localhost:37123   >>> SSH >>>   linux machine: localhost:37123


8. Inicie JConsole / Java VisualVM / Java Mission Control para conectarse a su proceso Java utilizando la siguiente URL

Esto funciona, porque JConsole / Java VisualVM / Java Mission Control cree que se conecta a un puerto en su máquina Windows local. pero Putty envía toda la carga útil al puerto 15666 de su máquina Linux.

En la máquina Linux, primero, el proceso java responde y devuelve el puerto RMIServer. En este ejemplo 37123.

Luego, JConsole / Java VisualVM / Java Mission Control cree que se conecta a localhost: 37123 y putty enviará toda la carga útil a la máquina Linux.

El proceso de Java responde y la conexión está abierta.

[x] Remote Process:
service:jmx:rmi:///jndi/rmi://localhost:<jndi-remote-port>/jmxrmi

Ejemplo:

[x] Remote Process:
service:jmx:rmi:///jndi/rmi://localhost:15666/jmxrmi


Conéctese a través de la URL del servicio jmx


9. DISFRUTE # 8-]


1
Solo una pequeña pregunta aquí: ¿no es posible hacer una conexión JMX sin rmi?
Kumar Vaibhav

5
Recibí una pista de que podemos configurar un rmi.port en un número de puerto fijo, de modo que podamos configurar el puerto arbitrario para la descarga de stubs de RMIServer. esto debería funcionar con la propiedad Java "com.sun.management.jmxremote.rmi.port = <rmi-server-port>". Parece una característica no documentada en Oracle Java VM.
sushicutta

1
Seguro es mejor que tener que configurar
almacenes de

Mismo proceso, pero no tengo ese objeto en la tabla
wener

2
@sushicutta, ¿puede agregar esta pista en su respuesta? Funciona perfectamente bien y puede eliminar los pasos del 4 al 6, el problema es que su puerto reenviado debe ser el mismo que el puerto original y tanto el puerto jmx como el rmi también deben ser igual
lamentable

80

Agregar -Djava.rmi.server.hostname='<host ip>'resolvió este problema para mí.


2
En mi caso, tengo que agregar la dirección IP (-Djava.rmi.server.hostname = <ip>). hostname -i me dio dos direcciones IP y la correcta fue la segunda en la lista.
Georgy Bolyuba

4
no resolvió el problema por mí. conectar windows-2-windows no es un problema para mí, PERO cuando intento conectarme desde un JVM Jvisualvm.exe en Windows para monitorear un servicio java que se ejecuta en SUSE con Oracle JDK 1.6.024, falla la conexión. Por esta razón, creo que la pregunta de esta persona sigue sin respuesta.
djangofan

Esto me solucionó el problema. Esto más el conjunto habitual de 3 (autenticar / puerto / ssl) y ahora puedo conectarme de forma remota. Sin embargo, el cuadro está escuchando en múltiples interfaces virtuales, puede haber sido la razón por la que no especificar el host confundió al jvm.
Nicholi

Finalmente resolví mis problemas al conectar jconsole en mi computadora portátil osx. Gracias.
rado

Trabajó para mi. ¡Gracias!
Jeff

58

Probado con Java 8 y versiones más recientes

Esta solución también funciona bien con firewalls.

1. Agregue esto a su script de inicio de Java en el host remoto:

-Dcom.sun.management.jmxremote.port=1616
-Dcom.sun.management.jmxremote.rmi.port=1616
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.local.only=false
-Djava.rmi.server.hostname=localhost

2. Ejecute esto en su computadora.

  • Usuarios de Windows :

    putty.exe -ssh user@remote-host -L 1616:remote-host:1616

  • Usuarios de Linux y Mac :

    ssh user@remote-host -L 1616:remote-host:1616

3. Inicie jconsoleen su computadora

jconsole localhost:1616

4. ¡Diviértete!

PD: durante el paso 2, use sshy -Lespecifique que el puerto 1616 en el host local (cliente) debe reenviarse al lado remoto. Este es un túnel ssh y ayuda a evitar firewalls o varios problemas de redes.


1
¡¡INCREÍBLE!! He estado intentando durante más de 6 horas con jmx-remote a una instancia de ActiveMQ en java8. ¡¡FINALMENTE ALGO QUE FUNCIONÓ !! ¡Gracias! :)
Rop

Gracias, como tú también luché durante un día, y después de tanto trabajo pensé: "¡¡Debo escribirle esto a SO !!"
freedev

2
Realmente apesta que Oracle no mencione "com.sun.management.jmxremote.rmi.port", "java.rmi.server.hostname" docs.oracle.com/javase/8/docs/technotes/guides/management/… I Supongo que ese fue mi problema.
Rop

Porque, AFAIK, este problema no se trata de JMX, sino de cómo funciona RMI. Por ejemplo, después de este caso, tuve el mismo problema con jmeter, que usa rmi en su implementación cliente / servidor.
freedev

2
Funciona. Simplemente agregando mi experiencia con los túneles: 1) puedo usar "localhost" en "-L 1616: localhost: 1616" 2) no puedo cambiar el puerto de origen, es decir, esto no funcionará: "-L 9999: localhost: 1616"
gargii

19

Probablemente esté experimentando un problema con un firewall. El 'problema' es que el puerto que especifica no es el único puerto utilizado, utiliza 1 o tal vez 2 puertos más para RMI, y estos probablemente estén bloqueados por un firewall.

Uno de los puertos adicionales no se sabrá de antemano si usa la configuración RMI predeterminada, por lo que debe abrir una gran variedad de puertos, lo que puede que no divierta al administrador del servidor.

Hay una solución que no requiere abrir muchos puertos, sin embargo, la he hecho funcionar usando los fragmentos de código fuente combinados y los consejos de

http://forums.sun.com/thread.jspa?threadID=5267091 - el enlace ya no funciona

http://blogs.oracle.com/jmxetc/entry/connecting_through_firewall_using_jmx

http://java.sun.com/javase/6/docs/technotes/guides/management/agent.html

Incluso es posible configurar un túnel ssh y aun así hacer que funcione :-)


2
Pude evitar el firewall usando solo el alias descrito en simplygenius.com/2010/08/jconsole-via-socks-ssh-tunnel.html junto con la configuración -Djava.rmi.server.hostname como se menciona en otra respuesta aquí.
Damien

Nota para los futuros lectores: el enlace a forums.sun.comestá roto
CDspace

1
Nota para los futuros lectores: el enlace a blogs.oracle.comestá roto.
Grimlock

17

Después de poner a prueba mi Google-fu durante los últimos días, finalmente pude hacer que esto funcionara después de compilar las respuestas de Stack Overflow y esta página http://help.boomi.com/atomsphere/GUID-F787998C- 53C8-4662-AA06-8B1D32F9D55B.html .

Volver a publicar desde la página de Dell Boomi:

To Enable Remote JMX on an Atom

If you want to monitor the status of an Atom, you need to turn on Remote JMX (Java Management Extensions) for the Atom.

Use a text editor to open the <atom_installation_directory>\bin\atom.vmoptions file.

Add the following lines to the file:

-Dcom.sun.management.jmxremote.port=5002
-Dcom.sun.management.jmxremote.rmi.port=5002
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false

La única línea que no he visto ninguna cubierta de respuesta de Stack Overflow es

-Dcom.sun.management.jmxremote.rmi.port=5002

En mi caso, estaba intentando recuperar las métricas de Kakfa, así que simplemente cambié la opción anterior para que coincida con el -Dcom.sun.management.jmxremote.portvalor. Entonces, sin autenticación de ningún tipo, la configuración mínima debería tener este aspecto:

-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.port=(jmx remote port)

-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.rmi.port=(jmx remote port)
-Djava.rmi.server.hostname=(CNAME|IP Address)

1
Más uno para "Google-fu"
kevinarpe

"com.sun.management.jmxremote.rmi.port" también fue la clave para mí. Vea también esta respuesta: stackoverflow.com/a/22306586/123205
David

No necesitaba "com.sun.management.jmxremote.local.only", así que no creo que su configuración sea realmente "mínima"
David


7

Los pasos 4 a 7 de Sushicutta se pueden omitir agregando la siguiente línea al paso 3:

-Dcom.sun.management.jmxremote.rmi.port=<same port as jmx-remote-port>

Por ejemplo, agregar para iniciar los parámetros:

-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=12345
-Dcom.sun.management.jmxremote.rmi.port=12345
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.local.only=false
-Djava.rmi.server.hostname=localhost

Para el reenvío de puertos, conéctese usando:

ssh -L 12345:localhost:12345 <username>@<host>

Si su host es un trampolín, simplemente encadene el puerto hacia adelante ejecutando lo siguiente en el escalón después de lo anterior:

ssh -L 12345:localhost:12345 <username>@<host2>

Cuenta que el nombre de host = localhost es necesario para asegurarse de que el jmxremote está diciendo la conexión RMI para utilizar el túnel. De lo contrario, podría intentar conectarse directamente y atacar el firewall.


Este método me ayuda: (1) agrego parámetros JMX perdidos y reinicio la aplicación (2) Luego ejecuto ssh -L <JMX_port>:localhost:<JMX_port> <remote_user>@<remote_host> en la máquina local (3) Luego me conecto a JMX remoto usando: jconsole <remote_host>:<JMX_port>
Rib47

6

PROTIP:

El puerto RMI se abre en puertos arbitrarios. Si tiene un firewall y no desea abrir los puertos 1024-65535 (o usar vpn), debe hacer lo siguiente.

Necesita arreglar (como si tuviera un número conocido) el Registro RMI y los puertos del servidor JMX / RMI. Para hacer esto, coloque un archivo jar (catalina-jmx-remote.jar está en el extra) en el lib-dir y configure un oyente especial en el servidor:

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

(Y, por supuesto, las banderas habituales para activar JMX

    -Dcom.sun.management.jmxremote  \
    -Dcom.sun.management.jmxremote.ssl=false \
    -Dcom.sun.management.jmxremote.authenticate=false \
    -Djava.rmi.server.hostname=<HOSTNAME> \

Consulte: Escucha del ciclo de vida remoto de JMX en http://tomcat.apache.org/tomcat-6.0-doc/config/listeners.html

Entonces puedes conectarte usando esta horrible URL:

service:jmx:rmi://<hostname>:10002/jndi/rmi://<hostname>:10001/jmxrmi

Probé lo anterior con el jar de extras, y puedo ver los puertos RMI escuchando como se especifica, pero RMI todavía usa puertos aleatorios después de conectarse al puerto JVM con VisualVM. Solución alternativa: busque puertos con 'lsof -i' y abra aquellos con conexiones bloqueadas.
Joseph Lust

5

Compruebe si su servidor está detrás del firewall. JMX se basa en RMI, que abre dos puertos cuando se inicia. Uno es el puerto de registro, el valor predeterminado es 1099 y se puede especificar mediante la com.sun.management.jmxremote.portopción. El otro es para la comunicación de datos y es aleatorio, que es lo que causa el problema. Una buena noticia es que, desde JDK6, este puerto aleatorio se puede especificar mediante la com.sun.management.jmxremote.rmi.portopción.

export CATALINA_OPTS="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=8991 -Dcom.sun.management.jmxremote.rmi.port=8991 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false"

4

Pasar JMX a través del Firewall es realmente difícil. El problema es que RMI estándar usa un segundo puerto asignado aleatoriamente (al lado del registro RMI).

Tenemos tres soluciones que funcionan, pero cada caso necesita una diferente:

  1. JMX sobre SSH Tunnel con proxy Socks, utiliza RMI estándar con SSH magic http://simplygenius.com/2010/08/jconsole-via-socks-ssh-tunnel.html

  2. JMX MP (alternativa al RMI estándar), usa solo un puerto fijo, pero necesita un jar especial en el servidor y el cliente http://meteatamel.wordpress.com/2012/02/13/jmx-rmi-vs-jmxmp/

  3. Inicie el código de formulario del servidor JMX, allí es posible usar RMI estándar y usar un segundo puerto fijo: https://issues.apache.org/bugzilla/show_bug.cgi?id=39055


Todas las demás respuestas deben ser una adición a esta
ruruskyi

2

Al probar / depurar / diagnosticar problemas remotos de JMX, primero intente siempre conectarse en el mismo host que contiene el MBeanServer (es decir, localhost), para descartar la red y otros problemas no específicos de JMX.


2

Ya hay algunas respuestas geniales aquí, pero hay un enfoque un poco más simple que creo que vale la pena compartir.

El enfoque de sushicutta es bueno, pero es muy manual, ya que debe obtener el puerto RMI cada vez. Afortunadamente, podemos solucionarlo utilizando un proxy SOCKS en lugar de abrir explícitamente los túneles del puerto. La desventaja de este enfoque es que la aplicación JMX que ejecuta en su máquina debe poder configurarse para usar un Proxy. En la mayoría de los procesos puede hacer esto agregando propiedades de Java, pero algunas aplicaciones no lo admiten.

Pasos:

  1. Agregue las opciones de JMX al script de inicio para su servicio Java remoto:

    -Dcom.sun.management.jmxremote=true
    -Dcom.sun.management.jmxremote.port=8090
    -Dcom.sun.management.jmxremote.ssl=false
    -Dcom.sun.management.jmxremote.authenticate=false
    
  2. Configure una conexión de proxy SOCKS a su máquina remota:

    ssh -D 9696 user@remotemachine.com
    
  3. Configure su aplicación de monitoreo de Java local para usar el proxy SOCKS (localhost: 9696). Nota: a veces puede hacer esto desde la línea de comando, es decir:

    jconsole -J-DsocksProxyHost=localhost -J-DsocksProxyPort=9696
    

2

Lo siguiente funcionó para mí (aunque creo que el puerto 2101 realmente no contribuyó a esto):

-Dcom.sun.management.jmxremote.port=2100
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.rmi.port=2101
-Djava.rmi.server.hostname=<IP_ADDRESS>OR<HOSTNAME>

Me estoy conectando desde una máquina remota a un servidor que tiene Docker en ejecución y el proceso está dentro del contenedor. Además, detuve el firewallD, pero no creo que ese fuera el problema, ya que podía hacer telnet a 2100 incluso con el firewall abierto. Espero eso ayude.


1

Estoy ejecutando JConsole / JVisualVm en Windows con conexión a tomcat que ejecuta Linux Redhat ES3.

Desactivar el filtrado de paquetes con el siguiente comando funcionó para mí:

/usr/sbin/iptables -I INPUT -s jconsole-host -p tcp --destination-port jmxremote-port -j ACCEPT

donde jconsole-host es el nombre de host o la dirección de host en la que se ejecuta JConsole y jmxremote-port es el número de puerto configurado para com.sun.management.jmxremote.port para la administración remota.


2
no funcionó para mí en una instancia de SUSE Amazon EC2. Creo que el problema está en otra parte.
djangofan

1

Estoy usando boot2docker para ejecutar contenedores Docker con Tomcat adentro y tengo el mismo problema, la solución fue:

  • Añadir -Djava.rmi.server.hostname=192.168.59.103
  • Utilizar el mismo puerto JMX en contenedor de host y estibador, por ejemplo: docker run ... -p 9999:9999 .... El uso de puertos diferentes no funciona.

0

También debe asegurarse de que el nombre de su máquina se resuelva en la IP a la que se vincula JMX; NO localhost ni 127.0.0.1. Para mí, ha ayudado a poner una entrada en hosts que defina explícitamente esto.


0

Pasar JMX a través del firewall no es tan difícil en absoluto. Hay una pequeña trampa. Tienes que reenviar tanto tu puerto configurado JMX, es decir. 9010 y uno de los puertos dinámicos que escucha en mi máquina era> 30000


0

Estos son los pasos que funcionaron para mí (debian detrás del firewall en el lado del servidor, alcanzado a través de VPN desde mi Mac local):

comprobar la ip del servidor

hostname -i

utilizar parámetros de JVM:

-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=[jmx port]
-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Djava.rmi.server.hostname=[server ip from step 1]

ejecutar la aplicación

encontrar el pid del proceso java en ejecución

comprobar todos los puertos utilizados por JMX / RMI

netstat -lp | grep [pid from step 4]

abra todos los puertos del paso 5 en el firewall

Voila.


0

Para hacer una contribución, esto es lo que hice en CentOS 6.4 para Tomcat 6.

  1. Apagar el servicio iptables

    service iptables stop
    
  2. Agregue la siguiente línea a tomcat6.conf

    CATALINA_OPTS="${CATALINA_OPTS} -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=8085 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=[host_ip]"
    

De esta manera pude conectarme desde otra PC usando JConsole.


0

Estoy intentando que JMC ejecute Flight Recorder (JFR) para perfilar NiFi en un servidor remoto que no ofrece un entorno gráfico en el que ejecutar JMC.

Basado en las otras respuestas dadas aquí, y luego de muchas pruebas y errores, esto es lo que estoy proporcionando a la JVM ( conf / bootstrap.conf ) cuando lanzo NiFi:

java.arg.90=-Dcom.sun.management.jmxremote=true
java.arg.91=-Dcom.sun.management.jmxremote.port=9098
java.arg.92=-Dcom.sun.management.jmxremote.rmi.port=9098
java.arg.93=-Dcom.sun.management.jmxremote.authenticate=false
java.arg.94=-Dcom.sun.management.jmxremote.ssl=false
java.arg.95=-Dcom.sun.management.jmxremote.local.only=false
java.arg.96=-Djava.rmi.server.hostname=10.10.10.92  (the IP address of my server running NiFi)

Puse esto en / etc / hosts , aunque dudo que sea necesario:

10.10.10.92   localhost

Luego, al iniciar JMC, creo una conexión remota con estas propiedades:

Host: 10.10.10.92
Port: 9098
User: (nothing)
Password: (ibid)

Por cierto, si hago clic en la URL del servicio JMX personalizado, veo:

service:jmx:rmi:///jndi/rmi://10.10.10.92:9098/jmxrmi

Esto finalmente lo hizo por mí.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.