如何远程访问 Spring-boot JMX
How to access Spring-boot JMX remotely
我知道 spring 会自动公开 JMX bean。我能够使用 VisualVM 在本地访问它。
但是在产品上我如何使用它的 JMX bean 远程连接到应用程序?是否有默认端口或者我应该另外定义什么?
谢谢,
雷.
在“$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
它不启用安全性,但会帮助您连接到远程服务器。
默认情况下,JMX 可在本地自动访问,因此 运行 jconsole
locally 会在不公开端口的情况下检测所有本地 java 应用程序。
要通过 JMX 远程访问应用程序,您必须指定一个 RMI 注册表端口。需要知道的是,在连接时,JMX 在该端口上初始化,然后 然后 在 随机高位建立数据连接 端口,如果中间有防火墙,这是个大问题。 (“嘿,系统管理员,打开所有内容,好吗?”)。
要强制 JMX 重新连接到您已建立的同一端口,您有以下几个选项。注意:您可以为 JMX 和 RMI 使用不同的端口,也可以使用相同的端口。
选项 1:命令行
-Dcom.sun.management.jmxremote.port=$JMX_REGISTRY_PORT
-Dcom.sun.management.jmxremote.rmi.port=$RMI_SERVER_PORT
如果您正在使用 Spring 启动,您可以将其放入与 (appname).jar
部署一起存在的 (appname).conf
文件中。
选项 2:Tomcat/Tomee 配置
配置一个JmxRemoteLifecycleListener:
Maven 罐子:
<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 host/port 和 jndi:rmi host/port。如果同时指定两者,则不会出现随机高“问题”。
编辑: 要使 JMX 远程处理工作,您需要做出有关身份验证的决定。最好分 3 个不同的步骤进行:1) 使用 -Dcom.sun.management.jmxremote.authenticate=false
进行基本设置,然后 2) 添加密码文件 (-Dcom.sun.management.jmxremote.password.file
)。 See here for instructions. + -Dcom.sun.management.jmxremote.ssl=false
然后 3) 设置 SSL。
在 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
.......
jar 是从 Here 下载的。
另一种选择
Reference for jmxremote.password and jmxremote.access files
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.jmx.support.ConnectorServerFactoryBean;
import org.springframework.remoting.rmi.RmiRegistryFactoryBean;
@Configuration
public class ConfigureRMI {
@Value("${jmx.rmi.password.file:/tmp/jmxremote.password}")
private String passwordFile;
@Value("${jmx.rmi.access.file:/tmp/jmxremote.access}")
private String accessFile;
@Value("${jmx.rmi.port:19999}")
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");
Map<String, Object> properties = new HashMap<>();
properties.put("jmx.remote.x.password.file", passwordFile);
properties.put("jmx.remote.x.access.file", accessFile);
connectorServerFactoryBean.setEnvironmentMap(properties);
connectorServerFactoryBean.setServiceUrl(String.format("service:jmx:rmi:///jndi/rmi://:%s/jmxrmi", rmiPort));
return connectorServerFactoryBean;
}
}
我知道 spring 会自动公开 JMX bean。我能够使用 VisualVM 在本地访问它。
但是在产品上我如何使用它的 JMX bean 远程连接到应用程序?是否有默认端口或者我应该另外定义什么?
谢谢, 雷.
在“$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
它不启用安全性,但会帮助您连接到远程服务器。
默认情况下,JMX 可在本地自动访问,因此 运行 jconsole
locally 会在不公开端口的情况下检测所有本地 java 应用程序。
要通过 JMX 远程访问应用程序,您必须指定一个 RMI 注册表端口。需要知道的是,在连接时,JMX 在该端口上初始化,然后 然后 在 随机高位建立数据连接 端口,如果中间有防火墙,这是个大问题。 (“嘿,系统管理员,打开所有内容,好吗?”)。
要强制 JMX 重新连接到您已建立的同一端口,您有以下几个选项。注意:您可以为 JMX 和 RMI 使用不同的端口,也可以使用相同的端口。
选项 1:命令行
-Dcom.sun.management.jmxremote.port=$JMX_REGISTRY_PORT
-Dcom.sun.management.jmxremote.rmi.port=$RMI_SERVER_PORT
如果您正在使用 Spring 启动,您可以将其放入与 (appname).jar
部署一起存在的 (appname).conf
文件中。
选项 2:Tomcat/Tomee 配置
配置一个JmxRemoteLifecycleListener:
Maven 罐子:
<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 host/port 和 jndi:rmi host/port。如果同时指定两者,则不会出现随机高“问题”。
编辑: 要使 JMX 远程处理工作,您需要做出有关身份验证的决定。最好分 3 个不同的步骤进行:1) 使用 -Dcom.sun.management.jmxremote.authenticate=false
进行基本设置,然后 2) 添加密码文件 (-Dcom.sun.management.jmxremote.password.file
)。 See here for instructions. + -Dcom.sun.management.jmxremote.ssl=false
然后 3) 设置 SSL。
在 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
.......
jar 是从 Here 下载的。
另一种选择
Reference for jmxremote.password and jmxremote.access files
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.jmx.support.ConnectorServerFactoryBean;
import org.springframework.remoting.rmi.RmiRegistryFactoryBean;
@Configuration
public class ConfigureRMI {
@Value("${jmx.rmi.password.file:/tmp/jmxremote.password}")
private String passwordFile;
@Value("${jmx.rmi.access.file:/tmp/jmxremote.access}")
private String accessFile;
@Value("${jmx.rmi.port:19999}")
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");
Map<String, Object> properties = new HashMap<>();
properties.put("jmx.remote.x.password.file", passwordFile);
properties.put("jmx.remote.x.access.file", accessFile);
connectorServerFactoryBean.setEnvironmentMap(properties);
connectorServerFactoryBean.setServiceUrl(String.format("service:jmx:rmi:///jndi/rmi://:%s/jmxrmi", rmiPort));
return connectorServerFactoryBean;
}
}