我知道spring会自动暴露JMX bean。我能够使用VisualVM在本地访问它。
然而,在prod上如何使用它的JMX bean远程连接到应用程序?是否有默认端口或我应该另外定义任何东西?
谢谢, 射线。
答案 0 :(得分:40)
默认情况下,JMX可以在本地自动访问,因此在本地运行jconsole
可以检测到所有本地Java应用程序,而无需端口暴露。
要通过JMX 远程访问应用程序,您必须指定RMI注册表端口。要知道的是,在连接时,JMX在该端口上初始化, 然后 在随机高端口上建立数据连接,这是如果你的中间有防火墙,这是一个很大的问题。 (“嘿系统管理员,只是打开一切,mkay?”)。
要强制JMX在您建立的同一端口上重新连接,您有几个选择:
选项1:命令行
-Dcom.sun.management.jmxremote.port=$JMX_REGISTRY_PORT
-Dcom.sun.management.jmxremote.rmi.port=$RMI_SERVER_PORT
如果您使用的是Spring Boot,可以将其放在(appname).conf
部署的(appname).jar
文件中。
选项2:Tomcat / Tomee配置
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主机/端口。如果同时指定两者,则不会出现随机的高“问题”。
答案 1 :(得分:26)
在“$ JAVA_OPTS”中添加以下JVM属性(在您的应用程序中):
-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>
在Jconsole / Visual VM中使用以下内容进行连接:
service:jmx:rmi:///jndi/rmi://<HOST'S_IP>:<PORT_NUMBER>/jmxrmi
它不支持安全性,但可以帮助您连接到远程服务器。
答案 2 :(得分:3)
Java 1.8.0_71和Spring Boot(1.3.3.RELEASE)上的测试方法。 将以下参数附加到受监视JVM的JVM参数。
-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
用于定义固定RMI注册表端口,com.sun.management.jmxremote.rmi.port
用于指示JVM使用固定RMI端口,但不使用随机端口。
通过设置,我可以通过防火墙将JVM客户端从远程主机连接到受监控的JVM,只需打开12348和12349端口。
我在远程计算机上使用java -jar cmdline-jmxclient-0.10.3.jar user:pwd hostip:12348
进行了测试,该计算机生成以下输出(仅用于演示缩短)。
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
.......
从Here下载jar。