如何远程访问Spring-boot JMX [英] How to access Spring-boot JMX remotely
问题描述
我知道spring会自动公开JMX bean.我可以使用VisualVM在本地访问它.
但是在产品上,如何使用JMX Bean远程连接到应用程序?是否有默认端口,或者我还应该定义其他任何内容?
谢谢, 射线.
默认情况下,JMX可以在本地自动访问,因此在本地运行jconsole
会检测到所有本地Java应用程序,而不会暴露端口./p>
要通过JMX 远程访问应用,您必须指定一个RMI注册表端口.要知道的是,在连接时,JMX在该端口上初始化,然后 然后 在随机高端口上建立数据连接.如果中间有防火墙,则将是一个巨大的问题. (系统管理员,打开所有内容,对吗?").
要强制JMX重新连接到已建立的同一端口,您有几个选择:
选项1:命令行
-Dcom.sun.management.jmxremote.port=$JMX_REGISTRY_PORT
-Dcom.sun.management.jmxremote.rmi.port=$RMI_SERVER_PORT
如果您使用的是Spring Boot,则可以将其放入与(appname).jar
部署一起存储的(appname).conf
文件中.
选项2:Tomcat/Tomee配置
配置 JmxRemoteLifecycleListener :
Maven Jar:
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-catalina-jmx-remote</artifactId>
<version>8.5.9</version>
<type>jar</type>
</dependency>
配置server.xml:
<Listener className="org.apache.catalina.mbeans.JmxRemoteLifecycleListener"
rmiRegistryPortPlatform="10001" rmiServerPortPlatform="10002" />
选项3:以编程方式配置
@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;
}
}
您将发现,诀窍是serviceUrl
,您可以在其中指定jmx:rmi主机/端口和jndi:rmi主机/端口.如果同时指定两者,则不会出现随机性较高的问题".
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.
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 options:
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".
这篇关于如何远程访问Spring-boot JMX的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!