1. 程式人生 > >理解JMX之介紹和簡單使用

理解JMX之介紹和簡單使用

近期在專案上需要新增一些功能,想把一個開源工程整合進來,雖說是整合,但是覺得跟開發有查不了多少,要讓這個開源工程的編碼風格和設計方式與我們的工程保持一致,其中涉及到應用程式的監控和管理,不可避免的要使用JMX,之前簡單的瞭解過JMX,但是沒有動力深入去了解其中的原理和編碼,由於專案需要,這次針對JMX要深入總結一下,關於監控的內容,之前寫過一篇系統監控之SNMP協議理解,純屬是科普文章,也沒有程式設計實現過。但是其實監控對於一個軟體或者應用來說是很重要的,在InfoQ上有專門一系列文章來介紹監控系統的構建,聊聊監控(一):什麼值得監控以及監控指標的取捨,如果想深入瞭解可以看一下。

重回JMX,在寫本文之前,在網上找了很多的相關文章,讀的我一頭霧水,所以在本文中,我想把自己的理解用大白話說一下。

JMX的簡介

所謂JMX,是Java Management Extensions的縮寫,從官方的文件上來看,他就是一個框架,和JPA、JMS是一樣的,和我們平時使用的Spring、Hibernate也沒有什麼區別。就是通過將監控和管理涉及到的各個方面的問題和解決辦法放到一起,統一設計,以便向外提供服務,以供使用者呼叫,它的API在一下兩個地方:

  • java.lang.management:
  • javax.management.*:包括javax.management.loading、javax.management.modelmbean等;

資源管理

既然JMX涉及到的是監控和管理,那麼這它們都包括什麼?核心是針對資源

的一系列操作,什麼是資源?在我理解,只要是能幫助是你的活動和系統正常運轉的都算資源,那麼對於一個應用來說,資源可以是:

  • 硬體裝置
  • 計算機網路
  • 作業系統
  • 執行伺服器

可以稱之為資源的遠遠不止這些,比如執行這些的人員和開發者,也就是人力資源等。我們要做的就是對它們進行監控和管理,監控是為了及時發現問題,以便能夠及時提出正確的解決方案,避免損失;管理是為了預防問題的發生,同時也是為了使資源能夠得到有效的利用,使利益最大化。在監控和管理的時候要考慮的方面如下:

  • 監控硬體和平臺的執行情況:包括伺服器和作業系統等;
  • 合理配置資源:比如記憶體的配置是否合理,CPU是否足夠強大;
  • 收集應用執行的情況:比如說訪問量多大,響應時間是否夠快,哪個地區的訪問人數最多;
  • 在應用發生異常時能夠及時定位問題所在:這是監控的核心之一;

在沒有JMX之前,這些問題是如何解決的?我們可以想一下,每個資源嗎,對應的廠家都有自己的監控和管理元件,那麼如果想要全域性更改一個配置,可能會設計到很多的監控元件,想想都讓人頭疼!我們的目標是集中管理和監控,顯然之前那種環境是做不到這一點,但是通過JMX是可以的,這也是為什麼提出標準的人是最有發言權的人!關於上面所有的方面,JMX都能很好的支援。

JMX的術語

每個框架下都有自己的專業術語,這些專業術語可以在一定程度上展現這個框架的設計思想,比如Spring的bean,JPA的Entity等等。從JMX中涉及到術語也可以看出JMX的整個架構情況:

  • 管理資源(Manageable resource):像我在上面說的,只要是能幫助是你的活動和系統正常運轉的都算資源,可以是硬體、也可以是應用,只要能夠被Java的類描述即可;

  • 管理元件(MBean,managed bean):從資源的角度來看,它是一個對抽象的資源的一個描述,比如說如果資源是資料庫,管理元件中可以提供資料庫的一些描述資訊,比如資料庫伺服器的執行地址、埠,型別以及最大連線數等等,但是這個類必須滿足JMX規範中的提出的要求,比如命名規則和實現標準,類似於JavaBean。由於管理元件是資源的抽象,所以管理應用是直接面向MBean,也就說MBean會被暴露給管理應用來操作和訪問,通過MBean中提供的屬性和方法,MBean也有幾種型別,為了不添堵,如果沒有特殊說明,本文指的都是Standard MBean,關於它的具體使用在下面的編碼部分說明;

  • 管理元件伺服器(MBean Server):簡單的來看,它是一個容器,用來盛裝和管理一組MBeans,它是整個JMX管理環境的核心,由於其中有很多的MBean,所以它必須提供一種機制來區分各個MBean,這就是註冊機制,每個新增到MBean Server的MBean在註冊的時候都要提供一個ObjectName來區分彼此,MBean Server 通過這個ObjectName來查詢每個MBean,在JMX中是通過ObjectName類來為每個MBean提供唯一的一個標識,它包括兩部分:

    • 域名:這個域名通常是和想要註冊到的MBean Server的名稱標識相同,以便根據功能模組區分不同MBean Server中的MBean;
    • 鍵值對列表:被用來唯一的標識MBean,也提供了關於該MBean的資訊,形式如下:HelloAgent:name=helloWorld;其中的屬性不一定是真實的MBean的屬性,僅僅要求當和其他的MBean比較的時候能夠唯一標識,每個ObjectName中都要至少有一個屬性;

    當ObjectName重複的時候,註冊的時候會丟擲javax.management.InstanceAlreadyExistsException,在後面的編碼階段會著重說明這一點;

  • JMX代理(JMX Agent):它提供一系列的服務來管理一系列的MBeans,它是MBean Server的容器。JMX代理提供一些服務,包括建立MBean之間的關係,動態載入類,簡單監視服務,以及計時器;代理可以有一系列的協議介面卡(Protocol adapters )和聯結器(connectors ),協議介面卡和聯結器也是Java類,通常情況下也是MBeans,這些介面卡和聯結器是提供轉接功能而存在的,以便可以在遠端使用不同的協議,通過客戶端與這個代理連線,它內部可以對映到一個外部的協議或者暴露代理給遠端連線,這就意味著JMX代理可以被一系列不同的管理協議和工具使用,在本質上是外掛式架構的一種體現,體現了可插拔的思想;

  • 協議介面卡和聯結器(Protocol adapters and connectors ):協議介面卡和聯結器是JMX Agent中的物件,將代理暴露給不同的管理應用和協議,這個和不同的資料庫的驅動程式類似,每個資料庫都有自己的一套協議來聯絡,為了保持進行連線,就需要在JDBC應用和資料庫伺服器之間通過不同的驅動程式關聯。一個JMX Agent可以有任意數量的介面卡和聯結器;它們也是MBeans;

  • 通知(Notification ):通知是由MBeans和MBean Server 提出的,其中封裝了具體的事件和相應的資料。其他的MBeans或者Java物件可以註冊作為監聽器來接收這些通知,其實就是觀察者設計模式在JMX中的應用;

JMX的架構

JMX的架構是元件式的,被設計為三層:

  • 分佈層(Distributed layer):包含可以使管理應用與JMX Agents互動的元件。一旦通過互動元件與JMX Agents建立連線,使用者可以用管理工具來和註冊在Agents中的MBeans進行互動;
  • 代理層(Agent layer ):包含JMX Agent以及它們包含的MBean Servers。Agent layer的主要元件是MBean server,作為JMX Agents的核心,它充當MBeans的註冊中心。該層提供了4個Agent 服務來使對MBean的管理更容易:計時器(Timer)、監控(monitoring)、動態載入MBean(dynamic MBean loading )、關係服務(relationship services );
  • 指示層(Instrumentation layer ):包含代表可管理資源的MBeans。該層是最接近管理資源的,它由註冊在Agents中的MBeans組成,這個MBean允許通過JMX Agent來管理。每個MBean都暴露出來針對底層資源的操作和訪問;

具體的架構分層如下圖:

這裡寫圖片描述

JMX的簡單使用

  • 第一步:建立一個MBean介面,這個介面的名稱要以“MBean”結束,這是要暴露給管理應用使用的,但是具體其中是怎麼是實現的,管理應用是不會考慮的,MBean介面和相應的實現類如下:

    HelloWorldMBean.java:

    public interface HelloWorldMBean {
        String getGreeting();
        void setGreeting(String greeting);
        void printGreeting();
    }

    實現類HelloWorld.java:

    public class HelloWorld implements HelloWorldMBean {
        private String greeting;
    
        public HelloWorld(String greeting) {
            this.greeting = greeting;
        }
        public HelloWorld() {
            this.greeting = "hello world!";
        }
        public String getGreeting() {
            return greeting;
        }
        public void setGreeting(String greeting) {
            this.greeting = greeting;
        }
        public void printGreeting() {
            System.out.println(greeting);
        }
    }
  • 第二步:建立MBeanServer和JMX Agent,MBeanServer是在JMX Agent 中存在的,程式碼如下:

    public class HelloAgent implements NotificationListener {
        private MBeanServer mbs;
    
        public HelloAgent() {
            this.mbs = MBeanServerFactory.createMBeanServer("HelloAgent");
    
            HelloWorld hw = new HelloWorld();
            ObjectName helloWorldName = null;
            try{
                helloWorldName = new ObjectName("HelloAgent:name=helloWorld");
                mbs.registerMBean(hw, helloWorldName);
            } catch (Exception e) {
                e.printStackTrace();
            }
            startHtmlAdaptorServer();
        }
    
        public void startHtmlAdaptorServer(){
            HtmlAdaptorServer htmlAdaptorServer = new HtmlAdaptorServer();
            ObjectName adapterName = null;
            try {
                // 多個屬性使用,分隔
                adapterName = new ObjectName("HelloAgent:name=htmladapter,port=9092");
                htmlAdaptorServer.setPort(9092);
                mbs.registerMBean(htmlAdaptorServer, adapterName);
                htmlAdaptorServer.start();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String args[]){
            System.out.println(" hello agent is running");
            HelloAgent agent = new HelloAgent();
        }
    }
    • 首先建立MBean Server,並提供一個名稱來唯一標識該Server,這裡是使用工廠模式來建立該Server
    • 將我們建立的MBean註冊到MBean Server中,並提供ObjectName來唯一標識,這就是我們在上面提到的域名+屬性列表來唯一標識;
    • 建立一個Adaptor以便我們測試訪問,這裡使用的是HtmlAdaptorServer,這是sun公司之前提供的,我一直想通過maven導進來,但是並沒有發現這個包,無奈用到HtmlAdaptorServer類,需要用到jmxtools.jar, 可以去這裡下載,有兩個包:jmx-1_2_1-ri.zip; jmx_remote-1_0_1_03-ri.zip。jmx-1_2_1-ri.zip解壓後lib中有jmxri.jar和jmxtools.jar,將jmxtool.jar拷貝出來放入classpath中即可(jmxri.jar在JDK5+已經包被包含了);
    • 從上面可以看到HtmlAdaptorServer 也是一個MBean,也需要被加入到MBean Server中;

我一直覺得程式碼是理解概念和設計最好的方式,雖然一些官方文件和手冊經常不說人話,但是通過程式碼中的邏輯卻可以清清楚楚明白設計者的思想,所以在大體瞭解概念後,直接去接觸程式碼是最好不過的了!