본문 바로가기

WEB개발/JAVA

JMX(MBean), JOLOKIA, SpringBoot, Actuator

JMX(Java Management Extensions)

 

JMX(Java Management eXtensions)는 응용 프로그램(소프트웨어)/객체/장치 (프린터 등) 및 서비스 지향 네트워크 등을 감시 관리를 위한 도구를 제공하는 자바 API이다. 

 

JDK 1.5 이상부터 기본적으로 탑재된 기능 자바 어플리케이션의 모니터링과 관리 기능을 제공한다. Non-Java Resource와 하드웨어에 대해 wrapping한 인터페이스를 제공하며, API를 외부로 노출해 application 설정 및 통계데이터를 수집할 수 있는 기능을 제공한다.
mBean으로 알려진 하나 이상의 사용자 JavaBean 오브젝트를 통해(혹은 리소스를 호출하는) 애플리케이션, 디바이스, 서비스를 원격으로 제어할 수 있다.
mBean들은 mBean 서버에 등록되며, mBean 서버는 리소스에 접근하는 모든 원격 매니저를 관리한다.

 

  1. MBean(Managed Bean) 플랫폼 혹은 사용자에 의해 만들어진 모니터링용 객체.
  2. Standard MBean, Dynamic MBean, Model MBean, Open MBean 4가지 종류로 나뉨
  3. MBean Server : MBean을 등록. MBeans를 모니터링하기 원하는 원격 JMX 관리자는 MBean Server를 통하여 정보를 획득
  4. agent service : MBeans를 관리하는 (개발자가 제작한) 서비스 - client

MXBean( Managed Extended Bean )은 Java Management Extensions (JMX)의 일부로, JMX 프로토콜을 사용합니다. JMX 프로토콜은 Java 애플리케이션에서 모니터링 및 관리를 위한 표준화된 방법을 제공합니다.

 

 

RMI(Remote Method Invocation)는 기본적으로 TCP/IP 프로토콜을 사용하여 통신합니다. RMI는 자바에서 분산 객체 호출을 처리하는 메커니즘으로, 원격 서버에서 객체의 메서드를 로컬 객체처럼 호출할 수 있도록 해줍니다.
RMI의 통신 방식은 다음과 같습니다

1. 객체 전송: RMI는 원격 객체의 메서드를 호출하기 위해 네트워크를 통해 객체와 데이터를 전송합니다. 이 과정에서 기본적으로 TCP/IP를 사용하여 데이터가 송수신됩니다.

2. RMI 레지스트리: RMI는 "RMI 레지스트리"라는 서비스를 통해 원격 객체를 찾습니다. 클라이언트가 원격 객체를 호출하려면 먼저 RMI 레지스트리에서 객체를 조회한 후, TCP/IP 프로토콜을 통해 원격 객체와의 연결을 설정합니다.

3.RMI 통신: 원격 객체의 메서드를 호출할 때, 호출은 TCP/IP 네트워크를 통해 전달됩니다. Java RMI는 내부적으로 TCP/IP 기반의 소켓을 이용해 객체와 메서드 호출 정보를 전송하고, 그 결과를 클라이언트로 되돌려 보냅니다.


JMX 프로토콜은 RMI (Remote Method Invocation) 프로토콜을 기반으로 하며, 원격으로 JMX MBean을 연결하고 접근할 수 있도록 합니다. RMI는 자바 애플리케이션 간에 객체를 직접 주고받을 수 있도록 해주는 기술입니다.

따라서, MXBean은 RMI 프로토콜을 사용하여 JMX 서버와 클라이언트 사이의 통신을 처리하며, 자바 애플리케이션 간에 객체를 주고받을 수 있도록 합니다.

 

public interface MyMXBean {
   public void setMessage(String msg);
   public String getMessage();
}
public class MyMXBeanImpl implements MyMXBean {
   private String message;
   
   @Override
   public void setMessage(String msg) {
      message = msg;
   }
   
   @Override
   public String getMessage() {
      return message;
   }
}
public class MyMXBeanServer {
   public static void main(String[] args) throws Exception {
	   // MBeanServer 생성
      MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();

      // JMX 커넥터 생성
      String host = "127.0.0.1"; // 서버 IP 주소
      int port = 9999; // 서버 포트 번호

      // Rmi registry에 서버 IP, port를 설정한다.
      Registry registry = LocateRegistry.createRegistry(port);
      
      JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + host + ":" + port + "/server");
      JMXConnectorServer connector = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);
     
      
      // 커넥터 시작
      connector.start();

      // MBean 등록
      ObjectName mxbeanName = new ObjectName("jmx:type=MyMXBean");
      MyMXBean mxbean = new MyMXBeanImpl();
      mbs.registerMBean(mxbean, mxbeanName);
      
      // 클라이언트 요청 대기
      System.out.println("MXBean Server started, waiting for client requests...");
      Thread.sleep(Long.MAX_VALUE);
   }
}
public class MyMXBeanClient {
   public static void main(String[] args) throws Exception {
	  // JMX 커넥터 생성
      String host = "localhost"; // 서버 IP 주소
      int port = 9999; // 서버 포트 번호
      JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + host + ":" + port + "/server");
      JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
      MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
      
      // MBean 조회
      ObjectName mxbeanName = new ObjectName("jmx:type=MyMXBean");
      MyMXBean mxbean = JMX.newMXBeanProxy(mbsc, mxbeanName, MyMXBean.class);
      
      // MXBean 메서드 호출
      mxbean.setMessage("Hello, MXBean!");
      System.out.println(mxbean.getMessage());
      
      // 커넥터 종료
      jmxc.close();
   }
}

Jolokia

 

Jolokia는 REST API를 통해 JMX를 사용할 수 있도록 하는 라이브러리입니다. 따라서 Jolokia를 사용하면 원격으로 JMX 데이터를 검색하고 조작할 수 있습니다.

Jolokia는 JMX MBean을 HTTP 요청으로 노출하므로, 서버에 웹 애플리케이션이 설치되어 있어야 합니다.

JMX (Java Management Extensions)는 자바 애플리케이션의 모니터링 및 관리를 위한 표준 API이지만, JMX를 사용하는 것은 불편한 경우가 있습니다. JMX는 RMI (Remote Method Invocation)를 사용하여 원격 애플리케이션을 모니터링할 수 있지만, 보안 문제 및 네트워크 설정 등 다양한 이슈가 있을 수 있습니다.

Jolokia는 JMX 데이터를 HTTP REST API를 통해 노출하므로, 원격으로 JMX 데이터를 검색하고 조작할 수 있습니다. 이를 통해 네트워크 설정 및 보안 문제를 해결할 수 있으며, 더 간단한 방식으로 애플리케이션을 모니터링하고 관리할 수 있습니다.

또한, Jolokia는 다양한 프로토콜을 지원하므로, JMX 데이터를 다른 언어로 구현된 클라이언트에서도 사용할 수 있습니다. 이를 통해 다양한 플랫폼에서 동작하는 애플리케이션을 모니터링하고 관리할 수 있습니다.

따라서, Jolokia는 JMX의 보완적인 역할을 하며, 보안 문제 및 네트워크 설정 등을 해결할 수 있는 간편한 방식으로 애플리케이션을 모니터링하고 관리할 수 있도록 합니다.

 

public class MyMXBeanClient {
   public static void main(String[] args) throws Exception {
      // Jolokia Client 생성
      String host = "localhost"; // 서버 IP 주소
      int port = 8080; // 서버 포트 번호
      
      System.out.println(new URL("http", host, port, "").toString());
      
      J4pClient j4pClient = new J4pClient(new URL("http", host, port, "").toString());

      // MXBean 데이터 조회
      J4pReadRequest request = new J4pReadRequest("com.app.woo.jmx:type=MyMXBean", "Message");
      J4pReadResponse response = j4pClient.execute(request);

      // JSON 데이터 파싱
      Object value = response.getValue();
      if (value instanceof JSONObject) {
         JSONObject jsonObject = (JSONObject)value;
         String message = (String)jsonObject.get("Message");
         System.out.println("Message: " + message);
      }
   }
}

 

dependencies {
    implementation 'org.jolokia:jolokia-core:1.7.1'
    implementation 'org.jolokia:jolokia-jvm:1.7.1'
}

 

 


Actuator

Spring Actuator는 Spring Boot 애플리케이션의 상태와 동작을 모니터링하거나 관리할 수 있는 다양한 기능을 제공하는 서브 프로젝트입니다. 이를 통해 애플리케이션의 상태를 점검하고, 메트릭(metrics), 애플리케이션 설정, 사용 중인 스레드 정보 등을 노출하거나 조작할 수 있습니다.

 

주요 기능

  1. 모니터링 및 진단
    • 애플리케이션의 상태(health)를 확인하고, 의존성, 데이터베이스, 메시징 시스템 등의 연결 상태를 검사합니다.
    • 메모리 사용량, 활성 스레드 수, CPU 사용량 등 다양한 메트릭을 제공합니다.
  2. 엔드포인트 노출
    • HTTP로 접근 가능한 RESTful 엔드포인트를 통해 애플리케이션의 상태 정보를 제공합니다.
    • 기본적으로 /actuator 경로를 통해 엔드포인트를 접근합니다.
    • 예: /actuator/health, /actuator/metrics
  3. 확장성
    • 커스텀 엔드포인트를 정의하거나, 기본 엔드포인트를 확장할 수 있습니다.
    • 추가적인 모니터링이나 제어 로직을 쉽게 통합할 수 있습니다.
  4. 서드파티 통합
    • Prometheus, Grafana, ELK(Stack), Zipkin, Micrometer 등과 같은 모니터링/분석 도구와 손쉽게 연동할 수 있습니다.

 

주요 Actuator 엔드포인트

 

그 외 endpoint

https://docs.spring.io/spring-boot/reference/actuator/endpoints.html

 

Endpoints :: Spring Boot

If you add a @Bean annotated with @Endpoint, any methods annotated with @ReadOperation, @WriteOperation, or @DeleteOperation are automatically exposed over JMX and, in a web application, over HTTP as well. Endpoints can be exposed over HTTP by using Jersey

docs.spring.io

 

 

 

build.gradle

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-web'
	compileOnly 'org.projectlombok:lombok'
	annotationProcessor 'org.projectlombok:lombok'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
	testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

	// Spring Boot Actuator (JMX 지원 포함)
    implementation 'org.springframework.boot:spring-boot-starter-actuator'

	// https://mvnrepository.com/artifact/org.jolokia/jolokia-core
	implementation group: 'org.jolokia', name: 'jolokia-core', version: '1.7.2'
	implementation group: 'org.jolokia', name: 'jolokia-support-spring', version: '2.1.2'

}

 

application.properties

spring.jmx.enabled=true
# Actuator의 Jolokia 엔드포인트 활성화
management.endpoints.web.exposure.include=health,info,jolokia
management.endpoint.health.show-details=always
management.endpoint.jolokia.enabled=true

 

JVMMonitoringService.java

import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.OperatingSystemMXBean;
import java.lang.management.ThreadMXBean;

import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.stereotype.Component;

@Component
@ManagedResource(objectName = "com.example.mxbean.jolokia:type=JVMMonitoringService", description = "Custom MBean for Monitoring")
public class JVMMonitoringService implements JVMMonitoringServiceMBean {

    private final OperatingSystemMXBean osMXBean;
    private final MemoryMXBean memoryMXBean;
    private final ThreadMXBean threadMXBean;

    public JVMMonitoringService() {
        this.osMXBean = ManagementFactory.getOperatingSystemMXBean();
        this.memoryMXBean = ManagementFactory.getMemoryMXBean();
        this.threadMXBean = ManagementFactory.getThreadMXBean();
    }

    // 속성으로 정의
    @ManagedAttribute(description = "System Load Average")
    @Override
    public double getSystemLoadAverage() {
        return osMXBean.getSystemLoadAverage();
    }

    // 속성으로 정의
    @ManagedAttribute(description = "Heap Memory Usage")
    @Override
    public long getHeapMemoryUsage() {
        return memoryMXBean.getHeapMemoryUsage().getUsed();
    }

    // 속성으로 정의
    @ManagedAttribute(description = "Thread Count")
    @Override
    public int getThreadCount() {
        return threadMXBean.getThreadCount();
    }
}

 

 

JVMMonitoringServiceMBean.java

public interface JVMMonitoringServiceMBean {
    double getSystemLoadAverage();
    long getHeapMemoryUsage();
    int getThreadCount();
}

 

 

GET request

http://localhost:8080/actuator/jolokia/read/cohttp://m.example.mxbean.jolokia:type=JVMMonitoringService/HeapMemoryUsage

 

response

 

 


https://ko.wikipedia.org/wiki/JMX