I know that spring automatically expose JMX beans. I was able to access it locally using VisualVM.
However on prod how I can connect to remotely to the app using it's JMX beans? Is there a default port or should I define anything in addition?
Thanks, ray.
Remote JMX ConnectionsRight click anywhere in the blank area under the application tree and select Add JMX Connection. Provide the machine name and port number for a running JMX agent, that has been started with the appropriate system properties to allow remote management.
JMX is automatically enabled by default in a Spring Boot application. As a result, all of the Actuator endpoints are exposed as MBeans. And it sets us up nicely to expose any other bean in the Spring application context as an MBean.
Enables the JMX remote agent and creates a remote JMX connector to listen through the specified port. By default, the SSL, password, and access file properties are used for this connector. It also enables local monitoring as described for the com.
The console is accessible at http://localhost:8080/jmx-console. The JMX Console provides a raw view of the JMX MBeans which make up the server.
By default JMX is automatically accessible locally, so running jconsole
locally would detect all your local java apps without port exposure.
To access an app via JMX remotely you have to specify an RMI Registry port. The thing to know is that when connecting, JMX initializes on that port and then establishes a data connection back on a random high port, which is a huge problem if you have a firewall in the middle. ("Hey sysadmins, just open up everything, mkay?").
To force JMX to connect back on the same port as you've established, you have a couple of the following options. Note: you can use different ports for JMX and RMI or you can use the same port.
Option 1: Command line
-Dcom.sun.management.jmxremote.port=$JMX_REGISTRY_PORT -Dcom.sun.management.jmxremote.rmi.port=$RMI_SERVER_PORT
If you're using Spring Boot you can put this in your (appname).conf
file that lives alongside your (appname).jar
deployment.
Option 2: Tomcat/Tomee configuration
Configure a JmxRemoteLifecycleListener:
Maven Jar:
<dependency> <groupId>org.apache.tomcat</groupId> <artifactId>tomcat-catalina-jmx-remote</artifactId> <version>8.5.9</version> <type>jar</type> </dependency>
Configure your server.xml:
<Listener className="org.apache.catalina.mbeans.JmxRemoteLifecycleListener" rmiRegistryPortPlatform="10001" rmiServerPortPlatform="10002" />
Option 3: configure programmatically
@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; } }
The trick, you'll see, is the serviceUrl
in which you specify both the jmx:rmi host/port and the jndi:rmi host/port. If you specify both, you won't get the random high "problem".
Edit: For JMX remoting to work, you'll need to make a decision about authenticating. It's better to do it in 3 distinct steps: 1) basic setup with -Dcom.sun.management.jmxremote.authenticate=false
then 2) add a password file (-Dcom.sun.management.jmxremote.password.file
). See here for instructions. + -Dcom.sun.management.jmxremote.ssl=false
and then 3) set up SSL.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With