Come accedere a JMX Spring-boot da remoto

So che la spring espone automaticamente i fagioli JMX. Sono stato in grado di accedervi localmente usando VisualVM.

Tuttavia su prod come posso collegarmi in remoto all’app usando i suoi bean JMX? Esiste una porta predefinita o dovrei definire qualcosa in aggiunta?

Grazie, Ray.

Di default, JMX è accessibile automaticamente localmente, quindi eseguire jconsole localmente rileverà tutte le tue app java locali senza esposizione alla porta.

Per accedere a un’app tramite JMX in remoto, è necessario specificare una porta del Registro di sistema RMI. La cosa da sapere è che quando si connette, JMX si inizializza su quella porta e quindi stabilisce una connessione dati su una porta alta casuale , che è un grosso problema se si ha un firewall nel mezzo. (“Ehi amministratori di sistema, apri tutto, mkay?”).

Per forzare JMX a riconnettersi sulla stessa porta che hai stabilito, hai un paio di opzioni:

Opzione 1: riga di comando

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

Se stai usando Spring Boot puoi inserirlo nel tuo (appname).conf che vive accanto alla tua distribuzione (appname).jar .

Opzione 2: configurazione Tomcat / Tomee

Configura un JmxRemoteLifecycleListener :

Maven Jar:

   org.apache.tomcat tomcat-catalina-jmx-remote 8.5.9 jar  

Configura il tuo server.xml:

  

Opzione 3: configurare a livello di programmazione

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

Il trucco, vedrai, è il serviceUrl in cui si specifica sia l’host / porta jmx: rmi che l’host / porta jndi: rmi. Se specifichi entrambi, non otterrai il “problema” casuale elevato.

Aggiungi le seguenti proprietà JVM in “$ JAVA_OPTS” (nella tua applicazione):

 -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port= -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname= 

In Jconsole / Visual VM utilizzare quanto segue per connettersi:

 service:jmx:rmi:///jndi/rmi://:/jmxrmi 

Non abilita la sicurezza, ma ti aiuterà a connetterti al server remoto.

Un approccio testato su Java 1.8.0_71 e Spring Boot (1.3.3.RELEASE). Aggiungi sotto i parametri agli argomenti JVM per JVM monitorata.

 -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 viene utilizzato per definire la porta del registro RMI fissa e il com.sun.management.jmxremote.rmi.port viene utilizzato per indicare a JVM di utilizzare la porta RMI fissa, ma NON quella casuale.

Impostando ciò, sono in grado di connettere il client JVM dall’host remoto alla JVM monitorata tramite un firewall aprendo solo le porte 12348 e 12349.

Ho java -jar cmdline-jmxclient-0.10.3.jar user:pwd hostip:12348 test utilizzando l’utente java -jar cmdline-jmxclient-0.10.3.jar user:pwd hostip:12348 su una macchina remota, che genera l’output di sotto (abbreviato solo per la dimostrazione).

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

Il barattolo è scaricato da Qui .