2017년 2월 4일 토요일

jmx MBean


application 에서 감시할 항목을 MBean 으로 jmx 에 노출 시켜 application 을 모니터링 할 수 있다.

jmx  (2번 3번은 은 하나의 파일로 super - sub class 형식으로 작성가능)
1. mbean interface 생성
2. mbean 구현체 생성
3. mbean 구현체 jmx 에 등록 코드 작성
4. java 실행 with jmx option
5. jvisualvm 확인


* 표준 MBean Interface 생성 (※ 주의 interface  suffix -MBean
    - MBean  인터페이스는 감시할 항목 정의
public interface MonitoringMBean {
    long getExecuteTime();
    long getPollingCount();
    long getChannelPercentage();
}
* MBean Interface 구현
 - 구현체에서 jmx 에 등록할 항목의 을 return 한다.
  - interface 의 구현체의 접미사 MBean 을 제외하고 파일명이 같아야 한다.

public class Monitoring implements MonitoringMBean {

    public long getExecuteTime() {
        return MonitoringCounter.getInstance().getExecuteTime();
    }
    public long getPollingCount() {
        return MonitoringCounter.getInstance().getPollingCount();
    }
    public long getChannelPercentage() {
        return MonitoringCounter.getInstance().getChannelPercentage();
    }

}
* 모니터링 값 설정
- 여러 객체에서 MonitoringMBean 구현체인 Monitoring 객체에 값을 지정 하려면 싱글톤 방식으로 값을 전달해야 한다.
public class MonitoringCounter {
    private static MonitoringCounter counter;

    private long executeTime;
    private long pollingCount;
    private long channelPercentage;

    private MonitoringCounter() {
    }

    public static MonitoringCounter getInstance() {
        if(counter == null) {
            counter = new MonitoringCounter();
        }
        return counter;
    }

    public long getExecuteTime() {
        return executeTime;
    }

    public void setExecuteTime(long executeTime) {
        this.executeTime = executeTime;
    }

    public long getPollingCount() {
        return pollingCount;
    }

    public void setPollingCount(long pollingCount) {
        this.pollingCount = pollingCount;
    }

    public long getChannelPercentage() {
        return channelPercentage;
    }

    public void setChannelPercentage(long channelPercentage) {
        this.channelPercentage = channelPercentage;
    }

}

* MBean 등록
public class MonitoringExporter {
    private Monitoring monitoring;

    public MonitoringExporter() {
        try {
            this.monitoring = new Monitoring();

            MBeanServer server = ManagementFactory.getPlatformMBeanServer();
            // new ObjectName("임의의 MBean 명 :type=임의의 Type명");
            ObjectName jmxObjectName = new ObjectName("SomeApp:type=SomeType");
            server.registerMBean(monitoring, jmxObjectName);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     -Dcom.sun.management.jmxremote.port=9999(임의의 포트 - 사용자 설정)
     -Dcom.sun.management.jmxremote.ssl=false
     -Dcom.sun.management.jmxremote.authenticate=false
     *
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        MonitoringExporter exporter = new MonitoringExporter();
    }

}
* application 실행 java option 
 
-Dcom.sun.management.jmxremote.port=9999 (임의의 포트)
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false

* application

public class SomeApp {
    private Random rand;

    public SomeApp() {
        this.rand = new Random();
    }

    public void run() {
        System.out.println("do something.....");
        MonitoringCounter.getInstance().setChannelPercentage(rand.nextLong());
        MonitoringCounter.getInstance().setExecuteTime(rand.nextLong());
        MonitoringCounter.getInstance().setPollingCount(rand.nextLong());
    }

    public static void main(String[] args) throws Exception {
        MonitoringExporter.main(null);
        SomeApp someApp = new SomeApp();
        while(true) {
            someApp.run();
            Thread.sleep(1000);
        }
    }

}

* jvisualvm 확인 
  - MBeans 항목은 별도 jvisualvm 플러그인 설치
    visualvm > tools > plugins > Avaliable Plugins > VisualVM-MBeans
    또는 http://visualvm.java.net/pluginscenters.html 에서 현재 visualvm 버전의 plugin search

 > jvisualvm













* jmx reader

 - mbean 으로 등록된 모니터링 항목을 jvisualvm이 아닌 mbean api 로 application 에서 조회
 
public class JMXReader {

    private MBeanServerConnection server;

    /**
     * local connection
     */
    public JMXReader() {
        this.server = ManagementFactory.getPlatformMBeanServer();
    }

    /**
     * remote connection
     * remote 정의
     * 같은 서버(localhost) 이라도 java 로 실행시키는 app 이 다를 경우 remote 로 이해해야함
     * @param url
     * @throws IOException
     */
    public JMXReader(String url) throws IOException {
        JMXServiceURL serviceURL = new JMXServiceURL(url);
        /* java.io.IOException: The client has been closed. 발생 - 발생이유는 좀더 분석이 필요함
        try (JMXConnector jmxConnector = JMXConnectorFactory.connect(serviceURL)) {
            this.server = jmxConnector.getMBeanServerConnection();
        }
        */
        JMXConnector jmxConnector = JMXConnectorFactory.connect(serviceURL);
        this.server = jmxConnector.getMBeanServerConnection();
    }

    public String[] getDomains() {
        try {
            return this.server.getDomains();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     *
     * @param objectName 정규식 및 null 가능
     * null = all
     * *:* = all
     * SomeApp:*
     * Some*:type:S*
     *
     * @return
     */
    public Set getObjectNames(ObjectName objectName) {
        try {
            return Sets.newHashSet(
                    Optional.ofNullable(this.server.queryNames(
                            objectName
                            ,null
                    )).orElse(Sets.newHashSet()));
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     *
     * @param objectName MBean
     * @return
     */
    public List getAttributes(ObjectName objectName) {
        MBeanInfo info = null;
        try {
            info = this.server.getMBeanInfo(objectName);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Arrays.stream(Optional.ofNullable(info).map(MBeanInfo::getAttributes).orElse(new MBeanAttributeInfo[]{null})).map(MBeanAttributeInfo::getName).collect(toList());
    }

    /**
     *
     * @param objectName MBean
     * @param attrName MBean 항목
     * @return
     */
    public Object getAttributeValue(ObjectName objectName, String attrName) {
        try {
            return this.server.getAttribute(objectName, attrName);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }


    public static void main(String[] args) throws MalformedObjectNameException, IOException {

        // local
        JMXReader local = new JMXReader();
        System.out.println(local.getAttributeValue(new ObjectName("java.lang:type=GarbageCollector,name=PS MarkSweep"), "Name"));
        System.out.println("-------------------------- local end");

        // remote
        JMXReader remote = new JMXReader("service:jmx:rmi:///jndi/rmi://127.0.0.1:9999/jmxrmi");

        Arrays.stream(remote.getDomains()).forEach(System.out::println);
        System.out.println("-------------------------- domains end");

        remote.getObjectNames(new ObjectName("*:*")).forEach(System.out::println);
        System.out.println("-------------------------- objectNames end");

        remote.getAttributes(new ObjectName("SomeApp:type=SomeType")).forEach(System.out::println);
        System.out.println("-------------------------- attributes of SomeApp MBean  end");

        System.out.println(remote.getAttributeValue(new ObjectName("SomeApp:type=SomeType"), "ExecuteTime"));
        System.out.println("-------------------------- attribute value of SomeApp MBean ExecuteTime Attribute end");

    }
}

댓글 없음:

댓글 쓰기

Intelij 설정 및 plugin

1. preferences... (settings...) Appearance & Behavior > Appearance - Window Options        ✓   Show memory indicator Editor &...