your programing

스프링 부트 JMX에 원격으로 액세스하는 방법

lovepro 2023. 4. 2. 12:12
반응형

스프링 부트 JMX에 원격으로 액세스하는 방법

봄철이면 JMX 콩이 자동으로 노출된다는 걸 알아요.Visual VM을 사용하여 로컬로 액세스할 수 있었습니다.

하지만 JMX 빈을 사용하여 앱에 원격으로 연결하는 방법은 무엇입니까?디폴트 포트가 있습니까?또는 다른 포트를 정의해야 합니까?

고마워, 레이

디폴트로는 JMX는 로컬에서 자동으로 액세스 할 수 있기 때문에jconsole 포트 노출 없이 로컬 Java 앱을 모두 로컬로 탐지합니다.

JMX를 통해 원격으로 앱에 액세스하려면 RMI 레지스트리 포트를 지정해야 합니다.주의할 점은 연결 시 JMX가 해당 포트에서 초기화하고 랜덤 하이 포트로 데이터 접속을 다시 확립한다는 것입니다.이것은 중간에 방화벽이 있는 경우에는 큰 문제가 됩니다.(「이봐 sysadmins, just opening everything, mkay?」)

JMX를 설정한 포트와 같은 포트로 강제로 다시 연결하려면 다음 몇 가지 옵션이 있습니다.주의: JMX 와 RMI 에 다른 포토를 사용할 수도, 같은 포토를 사용할 수도 있습니다.

옵션 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 구성

Jmx Remote Life cycle Listener를 설정합니다.

메이븐 자:

    <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 호스트/포트를 모두 지정합니다.둘 다 지정하면 랜덤으로 높은 "문제"가 발생하지 않습니다.

편집: JMX 리모트가 기능하려면 인증에 대해 결정해야 합니다.3개의 다른 순서로 실행하는 것이 좋습니다.1) 기본 셋업과-Dcom.sun.management.jmxremote.authenticate=false다음으로 2) 패스워드 파일을 추가합니다.-Dcom.sun.management.jmxremote.password.file)의 순서에 대해서는, 여기를 참조해 주세요.+-Dcom.sun.management.jmxremote.ssl=false3) SSL을 셋업합니다.

"$JAVA"에 다음 JVM 속성 추가OPTS" (어플리케이션 내):

-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

보안을 활성화하지는 않지만 원격 서버에 연결하는 데 도움이 됩니다.

Java 1.8.0_71 및 Spring Boot(1.3.3)에서의 테스트된 접근법.해제).모니터링되는 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는 고정 RMI 포트를 사용하도록 JVM에 지시하기 위해 사용되며 랜덤 RMI 포트를 사용하지 않습니다.

이를 설정하면 12348 및 12349 포트를 여는 방화벽을 통해 리모트호스트에서 감시 대상 JVM에 JVM 클라이언트를 연결할 수 있습니다.

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
.......

이 항아리는 여기에서 다운로드됩니다.

또 다른 대안

jmxremote.password 및 jmxremote.access 파일 참조

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;
    }
}

언급URL : https://stackoverflow.com/questions/29412072/how-to-access-spring-boot-jmx-remotely

반응형