본문으로 건너뛰기

19.3 JMX 모니터링

JMX는 Java Management eXtensions의 약자로 자바 기반의 모든 애플리케이션을 모니터링하기 위해 만든 표준 기술이다. JDK에서 지원하는 표준이다. Java EE 애플리케이션 서버들은 JMX로 모니터링할 수 있도록 서버의 데이터 값들을 MBean(Management Bean) 형태로 제공하고 있다.

여기서 MBean은 JMX에서 모니터링 값을 제공하기 위한 빈이다. MBean의 종류는 표준 MBean, 동적 MBean, 모델 MBean, 오픈 MBean로 4가지가 있다. MBean들은 데이터값과 오퍼레이션(메서드)을 제공하기 때문에 JMX를 통해 모니터링 값을 가져오고 메서드도 실행할 수 있다.

JConsole

MBean을 모니터링하기 위한 jconsole이라는 툴을 JDK에서 제공하고 있다. JBoss EAP 6에서는 MBean과 JVM에 대한 모니터링뿐만 아니라 CLI 명령을 실행할 수 있도록 JConsole을 확장하였다. $JBOSS_HOME/bin/jconsole.sh 파일이 JBoss에서 확장한 JConsole을 실행하는 스크립트이다.

연결방법

실행된 jboss-module.jar 로 시작하는 프로세스를 클릭하면 JBoss 인스턴스에 접속된다.

Remote Process는 URI을 입력하여 원격의 JBoss 인스턴스에 접속할 수 있다. 여기서 URI는 Java에서 기본적으로 제공하는 방식과 다른 JBoss URI를 입력해야 한다.

JBoss EAP 6에서는 RMI를 사용하지 않고 NIO(Non Blocking IO)를 사용한 remoting을 사용한다. NIO를 사용하기 때문에 네트워크 데이터 전송 및 처리 속도가 RMI보다 훨씬 빠르다. JMX연결에도 remoting을 사용하기 위하여, remoting-jmx라는 프로토콜을 제공하고 있다.

원격의 JBoss EAP 6에 연결하려면 URI로 ‘service:jmx:remoting-jmx://192.168.0.11:9999’와 같이 입력하고 연결하면 된다. 여기서 9999 포트는 스탠드얼론 모드 서버의 관리 포트이다.

service:jmx:remoting-jmx://192.168.0.11:9999

도메인 모드일 경우에는 접속방법이 다르다. 도메인 컨트롤러에 접속하는 것이 아니다. 도메인 모드에서 JMX 정보는 도메인 컨트롤러가 가지고 있지 않다. 각각의 JBoss 인스턴스들이 JMX 정보를 개별적으로 제공하기 때문에, 개별 인스턴스의 Remoting 포트로 접속해야 한다. 아래와 같이 서버 인스턴스의 포트 오프셋 0일 경우 4447포트로 접속한다. 오프셋 100인 인스턴스에 접속하려면 4547 포트로 접속하면 된다.

service:jmx:remoting-jmx://192.168.0.11:4447

또, 도메인 모드에서 JMX를 사용하려면 domain.xml 파일에서 JMX 서브시스템의 use-management-endpoint를 false로 설정을 변경하여야 한다.

<subsystem xmlns="urn:jboss:domain:jmx:1.3">

<expose-resolved-model/>

<expose-expression-model/>

<remoting-connector use-management-endpoint="false"/>

JConsole을 사용하여 서버에 접속하면 다음과 같이 Java의 메모리 정보를 그래프로 출력한다. 탭을 변경하여 메모리, 스레드, 클래스 로딩상황, MBean 정보들을 확인할 수 있다.

MBean이 제공하는 메서드를 호출할 수 있다.

Java 코드에서 MBean 호출 방법

CLI를 호출하여 데이터를 파일로 저장하여 분석했던 것처럼, JMX가 제공하는 MBean 값들을 수집하여 주기적으로 저장하면 분석에 활용할 수 있을 것이다. JBoss에서는 일반적인 Java의 RMI가 아닌 remoting-jmx를 사용하기 때문에 다음과 같은 코드로 JBoss EAP 6의 MBean 값을 가져올 수 있다.

// Get a connection to the JBoss EAP MBean server on localhost

String host = "localhost";

int port = 4447; // remoting-jmx port

String urlString = System.getProperty("jmx.service.url", "service:jmx:remoting-jmx://" + host + ":" + port);

JMXServiceURL serviceURL = new JMXServiceURL(urlString);

Hashtable h = new Hashtable();

String[] credentials = new String[] { "admin", "opennaru!234" };

h.put("jmx.remote.credentials", credentials);

JMXConnector jmxConnector = JMXConnectorFactory.connect(serviceURL, h);

MBeanServerConnection connection = jmxConnector.getMBeanServerConnection();

Hashtable<String, String> table = new Hashtable<String, String>();

table.put("subsystem", "messaging");

table.put("hornetq-server", "default");

ObjectName name = ObjectName.getInstance("jboss.as", table);

Boolean started = (Boolean) connection.getAttribute(name, "started");

System.out.println(started);

jmxConnector.close();