web-dev-qa-db-fra.com

Comment accéder à distance à Spring-boot JMX

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.

28
rayman

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

43
inanutshellus

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.

26
Arnab Biswas

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 .

3
Popeye