Java管理擴充套件指南之MBean簡介

2017-08-03    分類:JAVA開發、程式設計開發、首頁精華0人評論發表於2017-08-03

本文由碼農網 – 蘇文鵬原創翻譯,轉載請看清文末的轉載要求,歡迎參與我們的付費投稿計劃

上一篇:Java管理擴充套件指南之JMX技術總覽

2  MBean簡介

2.1.  MBeans簡要介紹

本課程介紹JMX API的基本概念,它被稱之為被管理的bean,或者MBean。

MBean是一個被管理的Java物件,就像Javabean元件一樣,但是它遵從JMX規範的設計模式。MBean可以表示裝置、應用或者任何需要被管理的資源。MBeans暴露如下管理介面:

  • 一組可讀和可寫屬性,或者兩者兼而有之。
  • 一組呼叫方法。
  • 自我描述。

在MBean例項的生命週期中,管理介面都不會發生變化。MBeans可以在某種預定義的事件發生時傳送通知。

JMX規範定義了五種MBean:

  • 標準MBeans
  • 動態MBeans
  • 開放MBeans
  • 模型MBeans
  • MXBeans

本系列的例子主要介紹最簡單的MBeans型別-標準MBeans和MXBeans。

2.2.  標準MBeans

本章主要介紹標準MBean的簡單例子。

標準MBean通過編寫SomethingMBean的java介面進行定義,然後定義一個Java類Something實現介面SomethingMBean。SomethingMBean中的方法用於定義屬性和操作。預設情況下,每個方法都會定義一個操作。屬性和操作都是滿足特定設計模式的java類方法。標準MBean由MBean介面和一個實現類組成。MBean介面的方法列出所有暴露的屬性和操作。實現類實現MBean介面以此提供管理資源功能。

下面的章節介紹標準MBean的例子和一個簡單的JMX代理管理MBean。

2.2.1.  MBean介面

MBean介面HelloMBean,如下:

package com.example; 

public interface HelloMBean { 

    public void sayHello(); 
    public int add(int x, int y); 

    public String getName(); 

    public int getCacheSize(); 
    public void setCacheSize(int size); 
}

按照約定,MBean介面的名稱由其實現類名+MBean字尾組成。在本例中,MBean介面類為HelloMBean,Hello類實現該介面。

根據JMX規範,MBean介面由屬性(可讀getter方法或者可寫setter方法)和操作(暴露的方法)組成。HelloMBean介面定義了兩種方法:add()和sayHello()。

HelloMBean定義兩個屬性:Name是隻讀的(getter方法)String屬性,CacheSize是可讀且可寫的(getter和setter)int屬性。Getter和setter方法允許管理程式訪問並改變屬性的值。在JMX規範中,getter方法是以get開頭並且不能返回void的任何public方法。getter方法允許管理程式讀取屬性的值。Setter方法是以set開頭並且接收一個引數的任何public方法。setter方法允許管理程式修改屬性的值。

這些操作和屬性在MBean實現中展示。

2.2.2.  MBean實現

Hello類試下HelloMBean介面如下:

package com.example; 

public class Hello ... 
    implements HelloMBean { 
    public void sayHello() { 
        System.out.println("hello, world"); 
    } 

    public int add(int x, int y) { 
        return x + y; 
    } 

    public String getName() { 
        return this.name; 
    }  

    public int getCacheSize() { 
        return this.cacheSize; 
    } 

    public synchronized void setCacheSize(int size) {
        ...

        this.cacheSize = size; 
        System.out.println("Cache size now " + this.cacheSize); 
    } 
    ...

    private final String name = "Reginald"; 
    private int cacheSize = DEFAULT_CACHE_SIZE; 
    private static final int 
        DEFAULT_CACHE_SIZE = 200; 
}

Hello類實現HelloMBean。sayHello()和add()操作很簡單,實際操作可以可繁可簡,依操作簡繁而異。

同時,Hello定義了獲取Name屬性的getter方法和讀寫CacheSize屬性的getter和setter方法。本例中,Name屬性不會改變。然而,在實際場景中,該屬性隨著資源的執行,依然可以改變。例如,這個屬性值可以代表執行時間或者記憶體佔用。這裡,該屬性值為Reginald。
呼叫setCacheSize 方法使你可以修改CacheSize 的值(初始值為200)。真實場景中,改變CacheSize屬性值需要其他操作同時執行,例如申請、釋放記憶體。本例僅列印該值以確保其已經改變。然而,更復雜的操作絕不僅僅呼叫println()。

HelloMBean介面和其實現類Hello定義之後,便可以使用它們管理資源了,如下節所示。

2.2.3.  建立JMX代理管理資源

資源通過MBean裝配後,資源的管理可以通過JMX代理執行。

JMX代理的核心元件時MBean Server。MBean server是用於MBean進行註冊的物件管理伺服器,包括一系列的管理MBeans的服務。檢視MBeanServer的API文件瞭解MBean server實現詳情。

Main class實現了一個基本的JMX代理。

package com.example; 

import java.lang.management.*; 
import javax.management.*; 

public class Main { 

    public static void main(String[] args) 
        throws Exception { 

        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); 
        ObjectName name = new ObjectName("com.example:type=Hello"); 
        Hello mbean = new Hello(); 
        mbs.registerMBean(mbean, name); 

        ...

        System.out.println("Waiting forever..."); 
        Thread.sleep(Long.MAX_VALUE); 
    } 
}

JMX代理類Main首先獲取MBean server,MBean server通過呼叫 java.lang.management.ManagementFactory類的getPlatformMBeanServer()方法進行初始化。如果平臺之前沒有建立MBean server,getPlatformMBeanServer會自動呼叫JMX方法MBeanServerFactory.createMBeanServer()建立MBean server。Main中MBeanServer的例項名為mbs。

然後,Main類為MBean例項定義一個物件名(ObjectName)。每個JMX MBean必須有一個物件名。物件名是JMX類ObjectName的例項,必須滿足JMX規範的語法。即物件名必須包含一個域domain和一系列的key-value屬性值。Main中定義的物件名中,域domain是com.example(也就是MBean所在的包名)。同時,key-value屬性值宣告該物件名額屬性type值為Hello。

接下來建立Hello物件的例項mbean,該物件註冊到MBean server例項mbs中,註冊需傳遞mbean和物件名,註冊方法是MBeanServer.registerMBean()

Hello MBean註冊到MBean server後,Main就只需等待Hello執行管理操作。本例中,這些管理操作時呼叫sayHell()和add(),獲取和設定屬性值。

2.2.4.  執行標準MBean例項

完成例子中的各類後,你現在可以執行本例子。本例使用JConsole與MBean進行互動。

要執行本例,執行以下步驟:

a)儲存jmx_examples.zip到你的工作目錄。

b)在終端視窗中通過如下命令解壓壓縮包。

unzip jmx_examples.zip

c)在工作目錄中編譯java類。

javac com/example/*.java

d)如果你使用JDK6及其以上,使用如下命令啟動:

java com.example.Main

如果你執行低於JDK6以下的版本,你需要新增額外的啟動引數來暴露管理和監控介面。

java -Dcom.sun.management.jmxremote example.Main

Main類會列印資訊以確認其執行。

e)在本機另一個終端中啟動JConsole。

jconsole

新建連線對話方塊會展現可連線的、處於執行中的JMX代理列表。

f)在新建連線對話方塊中,選擇com.example.Main並連線。一組當前平臺的活動便會展現出來。

g)點選MBean標籤。該標籤展示所有註冊到MBean server的MBean。

h)在左側邊欄,展開MBean樹形結構的com.example節點。你會看到例子中的Hello。如果點選Hello,你可以看到它暴露的屬性和方法。

i)展開MBean樹形結構中Hello中的屬性。你會看到Hello類定義的MBean屬性。

j)更改CacheSize屬性值為150。在啟動Main程式的終端視窗中,會提示該屬性的值已經發生變化。

k)展開MBean屬性結構中Hello中的方法。你將可以看到sayHello和add方法。

l)通過點選sayHello按鈕呼叫sayHello操作。JConsole對話方塊將會提示你方法呼叫成功。Main啟動的終端視窗將會顯示“hello, world”。

m)點選add方法的按鈕,輸入兩個整形引數。JConsole的對話方塊將會給出結果。

n)通過點選“連線”->“退出”關閉JConsole。

2.3.  MXBean

本節介紹特殊的MBean,也稱之為MXBean。

MXBean是一種引用預定義資料型別的MBean。通過這種方式,您可以確保任何客戶機(包括遠端客戶機)都可以使用您的MBean,而不需要客戶機訪問代表MBean型別的特定的類。MXBean提供一種方便的方法來繫結資料,而不需要客戶端進行特殊的繫結操作。

類似於標準MBean,MXBean定義一個名為SomethingMXBeans的java介面和一個java類實現。然而,不同於標準MBans,MXBeans不需要java實現類必須名為Something。每個介面中的方法定義屬性或者操作。@MXBean註解可以用於註解Java介面,這樣介面的名稱就不必以MXBean為結尾了。

MXBeans包含於J2SE 5.0版本的java.lang.management包中。然而,除了java.lang.management中定義的一組標準MXBeans,使用者可以定義自己的MXBeans。

MXBeans的主要思想是:MXBean介面java.lang.management.MemoryMBean 中引用的諸如java.lang.managementMemoryUsage型別,該型別對映一組稱之為開放型別(定義為javax.management.openbean包中)的型別。對映的具體規則詳見MXBean規範。然而,對於簡單的諸如int、String型別的對映規則保持不變,而對於複雜型別MemoryUsage則對映為基本型別CompositeDataSupport。

MXBean的例子由如下檔案構成,你可以在jmx_examples.zip中找到。

  • QueueSampler定義MXBean介面
  • 實現上面介面的QueueSampler類
  • MXBean 介面的getQueueSample方法返回型別QueueSample類
  • Main類,程式啟動類

MXBean例子上述這些類實現如下動作:

  • 定義簡單的MXBean,管理Queue<String>型別的資源
  • 定義getter方法:getQueueSample返回Queue的快照QueueSample類,該類將如下類繫結在一起。
    • 快照時間
    • 佇列queue大小
    • 特定時間佇列queue的頭部
  • 將MXBean註冊到MBean server

2.3.1.  MXBean介面

如下程式碼展示示例QueueSamplerMXBean的MXBean介面:

package com.example; 

public interface QueueSamplerMXBean { 
    public QueueSample getQueueSample(); 
    public void clearQueue(); 
}

注意,你宣告一個MXBean介面的方式與宣告標準MBean介面的方式完全相同。QueueSamplerMXBean介面定義getter方法:getQueueSample和操作clearQueue。

2.3.2.  定義MXBean操作

QueueSampler例子中定義的MXBean操作如下:

package com.example; 

import java.util.Date; 
import java.util.Queue; 

public class QueueSampler 
                implements QueueSamplerMXBean { 

    private Queue<String> queue; 

    public QueueSampler (Queue<String> queue) { 
        this.queue = queue; 
    } 

    public QueueSample getQueueSample() { 
        synchronized (queue) { 
            return new QueueSample(new Date(), 
                           queue.size(), queue.peek()); 
        } 
    } 

    public void clearQueue() { 
        synchronized (queue) { 
            queue.clear(); 
        } 
    } 
}

QueueSampler實現MXBean介面中定義的getter方法getQueueSampler和clearQueue操作。getQueueSample操作返回QueueSample類的例項,該例項由java.util.Queue的peek方法和size方法和java.util.Data例項構造而成。

2.3.3.  定義MXBean介面返回的Java型別

QueueSampler 返回QueueSample型別的例項,程式碼如下:

package com.example; 

import java.beans.ConstructorProperties; 
import java.util.Date; 

public class QueueSample { 

    private final Date date; 
    private final int size; 
    private final String head; 

    @ConstructorProperties({"date", "size", "head"}) 
    public QueueSample(Date date, int size, 
                        String head) { 
        this.date = date; 
        this.size = size; 
        this.head = head; 
    } 

    public Date getDate() { 
        return date; 
    } 

    public int getSize() { 
        return size; 
    } 

    public String getHead() { 
        return head; 
    } 
}

在QueueSample類中,MXBean框架呼叫QueueSample中所有的getter 方法將自己轉化為CompositeDate型別的例項,同時使用@ConstructorProperities註解從CompositeData例項轉化為QueueSample例項。

2.3.4.  在MBean server中建立並註冊MXBean

截至目前,已經定義如下內容:一個MXBean介面和它的實現類,以及實現類的返回型別。然後,MXBean必須在MXBean server進行註冊。這些操作同樣由標準MBean中的Main啟動JMX代理,只不過相關的程式碼在標準MBean章節中沒有介紹。

package com.example; 

import java.lang.management.ManagementFactory; 
import java.util.Queue; 
import java.util.concurrent.ArrayBlockingQueue; 
import javax.management.MBeanServer; 
import javax.management.ObjectName; 

public class Main { 

    public static void main(String[] args) throws Exception { 
        MBeanServer mbs = 
            ManagementFactory.getPlatformMBeanServer(); 

        ...  
        ObjectName mxbeanName = new ObjectName("com.example:type=QueueSampler");

        Queue<String> queue = new ArrayBlockingQueue<String>(10);
        queue.add("Request-1");
        queue.add("Request-2");
        queue.add("Request-3");
        QueueSampler mxbean = new QueueSampler(queue);

        mbs.registerMBean(mxbean, mxbeanName);

        System.out.println("Waiting..."); 
        Thread.sleep(Long.MAX_VALUE); 
    } 
}

Main執行如下操作:

  • 獲得MBean server平臺。
  • 為MXBean:QueueSampler建立物件名。
  • 為MXBean:QueueSampler建立一個Queue的例項。
  • 將Queue的例項傳遞給QueueSampler。
  • 將MXBean註冊到MXBean server中。

2.3.5.  執行MXBean例項

MXBean例項詳見jmx_examples.zip。本例需要Java SE 6版本以上。執行步驟如下:

a)儲存jmx_examples.zip到工作目錄。

b)在終端視窗中解壓壓縮包。

Unzip jmx_exampless.zip

c)在工作目錄中編譯Java程式碼。

Javac com/example/*.java

d)啟動Main應用。終端會列印提示資訊。

Java com.example.Main

e)在本機不同的視窗中啟動JConsole。在新建連線對話方塊中,展示當前可連線的JMX代理列表。

Jconsole

f)在新建連線對話方塊中,選擇com.example.Main並點選連線按鈕。當前平臺的活動會展示出來。

g)點選MBean標籤。該標籤展示當前註冊到MBean server的MBeans。

h)在左側框架中,展開MBean樹形結構中的com.example節點。你將可以看到QueueSampler。如果你點選QueueSampler,你將看到暴露出來的屬性和方法。

i)展開屬性節點。你可以看到QueueSample屬性出現在右側標籤中,其值為javax.management.openmbean.CompositeDataSupport。

j)雙擊CompositeDataSupport。你可以看到QueueSample中date、head和size屬性(MXBean框架將QueueSample例項轉換為ComositeData)。如果將QueueSampler定義為標準的MBean而不是MXBean,JConsole就不會發現QueueSample類,因為它不會在它的類路徑中。如果QueueSampler是一個標準的MBean,在訪問QueueSample屬性值時,您將收到一個ClassNotFoundException訊息。通過JConsole等通用JMX客戶機連線到JMX代理時,QueueSampler演示了使用mxbean的有用性。

k)展開操作節點。可以看到clearQueue操作的按鈕。

l)點選clearQueue按鈕。視窗會提示clearQueue方法被呼叫。

m)再次展開屬性節點,雙擊CompositeDataSupport,head和sie的值將被重置。

通過“連線”->“退出”關閉JConsole。

譯文連結:http://www.codeceo.com/article/java-mbean.html
英文原文:Lesson: Introducing MBeans
翻譯作者:碼農網 – 蘇文鵬
轉載必須在正文中標註並保留原文連結、譯文連結和譯者等資訊。]

相關文章