Je sais que le printemps expose automatiquement les beans JMX. J'ai pu y accéder localement en utilisant VisualVM.
Cependant sur prod comment je peux me connecter à distance à l'application en utilisant ses beans JMX? Existe-t-il un port par défaut ou dois-je définir quelque chose en plus?
Merci, ray.
Par défaut, JMX est automatiquement accessible localement, donc exécuter jconsole
localement détecterait toutes vos applications locales Java sans exposition de port).
Pour accéder à une application via JMX à distance vous devez spécifier un port de registre RMI. La chose à savoir est que lors de la connexion, JMX s'initialise sur ce port et alors établit une connexion de données sur un port élevé aléatoire , ce qui est un énorme problème si vous avez un pare-feu au milieu. ("Salut les administrateurs système, ouvrez tout, mkay?").
Pour forcer JMX à se reconnecter sur le même port que vous avez établi, vous avez deux options:
Option 1: ligne de commande
-Dcom.Sun.management.jmxremote.port=$JMX_REGISTRY_PORT
-Dcom.Sun.management.jmxremote.rmi.port=$RMI_SERVER_PORT
Si vous utilisez Spring Boot, vous pouvez le mettre dans votre (appname).conf
fichier qui cohabite avec votre (appname).jar
déploiement.
Option 2: configuration Tomcat/Tomee
Configurer un JmxRemoteLifecycleListener :
Pot Maven:
<dependency>
<groupId>org.Apache.Tomcat</groupId>
<artifactId>Tomcat-catalina-jmx-remote</artifactId>
<version>8.5.9</version>
<type>jar</type>
</dependency>
Configurez votre server.xml:
<Listener className="org.Apache.catalina.mbeans.JmxRemoteLifecycleListener"
rmiRegistryPortPlatform="10001" rmiServerPortPlatform="10002" />
Option 3: configurer par programme
@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;
}
}
L'astuce, vous verrez, est le serviceUrl
dans lequel vous spécifiez à la fois l'hôte/port jmx: rmi et l'hôte/port jndi: rmi. Si vous spécifiez les deux, vous n'obtiendrez pas le "problème" aléatoire élevé.
Ajoutez les propriétés JVM suivantes dans "$ Java_OPTS" (dans votre application):
-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>
Dans la Jconsole/Visual VM utilisez ce qui suit pour vous connecter:
service:jmx:rmi:///jndi/rmi://<Host'S_IP>:<PORT_NUMBER>/jmxrmi
Il n'active pas la sécurité, mais vous aidera à vous connecter au serveur distant.
Une approche testée sur Java 1.8.0_71 et Spring Boot (1.3.3.RELEASE). Ajoutez les paramètres ci-dessous aux arguments JVM pour la JVM surveillée.
-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
Le com.Sun.management.jmxremote.port
est utilisé pour définir le port de registre RMI fixe et com.Sun.management.jmxremote.rmi.port
est utilisé pour demander à JVM d'utiliser un port RMI fixe, mais PAS d'en utiliser un au hasard.
En définissant cela, je peux connecter le client JVM de l'hôte distant à la JVM surveillée via un pare-feu ouvrant simplement le port 12348 et 12349.
J'ai testé en utilisant Java -jar cmdline-jmxclient-0.10.3.jar user:pwd hostip:12348
sur une machine distante, qui génère une sortie inférieure (raccourcie uniquement pour la démonstration).
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
.......
Le pot est téléchargé depuis ici .