如何远程访问Spring-boot JMX

ray*_*man 28 spring jmx spring-boot

我知道spring会自动暴露JMX bean.我能够使用VisualVM在本地访问它.

但是在prod上如何使用它的JMX bean远程连接到应用程序?是否有默认端口或我应该另外定义任何东西?

谢谢,雷.

ina*_*lus 44

默认情况下,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
Run Code Online (Sandbox Code Playgroud)

如果您使用的是Spring Boot,则可以将其放在(appname).conf(appname).jar部署一起存在的文件中.

选项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>
Run Code Online (Sandbox Code Playgroud)

配置server.xml:

<Listener className="org.apache.catalina.mbeans.JmxRemoteLifecycleListener"
      rmiRegistryPortPlatform="10001" rmiServerPortPlatform="10002" />
Run Code Online (Sandbox Code Playgroud)

选项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;
    }
}
Run Code Online (Sandbox Code Playgroud)

你会看到,你可以serviceUrl在其中指定jmx:rmi主机/端口和jndi:rmi主机/端口.如果同时指定两者,则不会出现随机高"问题".


Arn*_*was 27

在"$ 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>
Run Code Online (Sandbox Code Playgroud)

在Jconsole/Visual VM中使用以下连接:

service:jmx:rmi:///jndi/rmi://<HOST'S_IP>:<PORT_NUMBER>/jmxrmi
Run Code Online (Sandbox Code Playgroud)

它不支持安全性,但可以帮助您连接到远程服务器.


Pop*_*eye 6

在 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
Run Code Online (Sandbox Code Playgroud)

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
.......
Run Code Online (Sandbox Code Playgroud)

该 jar 是从Here下载的。