2025-02-09

1.  JMX規范
JMX是“Java管理擴展的”的縮寫,它和其他JavaEE類似也是曾經的Sun提出的一種規范(規約),從名字上可以看出主要是負責系統管理。是一個為系統加入或者說擴展成有管理功能的規約,隻要按照這套規約行事,您的系統,某些某塊就具備被其他工具(例如JConsole)管理的能力。換句話說就是可以用JMX來監控咱們的系統運行情況,還有可以在運行時環境像Web Service、RMI一樣調用系統管理類的一些方法。實現此規范的框架也很多:Spring、Tomcat、JBoss容器……
2.  場景簡述
咱們先假設一個情景,夫妻二人。男的因為工作需要要去外地出差,因公司規定,出差不能帶傢屬,女方不能跟過去啊。所以女方給他們2個人一個手機——HTC吧。裡面有個小程序,叫做JMXImpl4Android。等到男方出差在外地瞭,在外地出差的城市,一天晚上和同事散步,路上遇到個發廊(各位男性朋友明白的啊)。此時遠在另一個城市的妻子的手機突然響瞭,手機GIS定位信息告知妻子:“您的丈夫在一個發廊門前徘徊,請註意”。妻子急瞭,立刻給丈夫打電話:“你幹嘛呢?”。丈夫戰戰栗栗,汗出如漿,乖乖的回酒店玩DOTA瞭!
我們來用Java消息擴展的視角來看看這個場景,咱們偉大一些相當於那個妻子,那個丈夫就相當於咱們的系統,出差事件相當於咱們將系統部署到瞭真正的遠程的運行環境,妻子曾HTC手機給丈夫您可以理解成把丈夫打造成具有JMX規范的系統,換句話說:此丈夫可監控。因為一個小小的GIS應用就能讓妻子隨時監控丈夫的狀態——想邪惡一把,並且還可以根據系統的狀態進行相應的措施——打電話告訴丫的別想出軌,雖然新的婚姻法下來瞭,但是房子是老娘買的,出軌?你試試!
看到這裡,大傢估計明白瞭JMX是什麼東西,幹什麼用的瞭。但是估計大傢有一個疑問,這個和Java分佈式系統有什麼關系啊?在分佈式系統中有時候我們需要監控各個分機器的狀態,比如想知道機器此時此刻的Tomcat的運行狀況如何,還可以根據狀況調用相關的操作,比如shutdown服務、去除已部署的web工程等等與服務有關的操作。或者對於調度這些節點機的主控機器也可以進行監控,在遠程使用一個JConsole調用即可。Ok,說瞭這麼多,我們看示例吧,最後再來用實例解釋JMX的那些晦澀的理論概念。
3.  監控本機程序
這種場景在實際中不太常用,對於本機的程序來說,需要監控,按需調用被托管的類方法還真不多。
相當於丈夫就在你面前,他的一舉一動都在你眼皮底下,你還需要一個Android小程序去監控他嗎?筆者使用的是Spring3的實現。所以先將Spring的包下載下來,放到項目的classpath中。
咱們先寫一個最普通的JavaBean
Java代碼 
<span style="font-size: small;">package jmx; 
 
public class HusbandLocal { 
 
    // 屬性 
    private String name; 
    private int age; 
    private String message; 
 
    // set,get 
    public String getName() { 
        System.out.println("name:"+name); 
        return name; 
    } 
 
    public void setName(String name) { 
        this.name = name; 
    } 
 
    public int getAge() { 
        System.out.println("age:"+age); 
        return age; 
    } 
 
    public void setAge(int age) { 
        this.age = age; 
    } 
 
    public String getMessage() { 
        System.out.println("message:"+message); 
        return message; 
    } 
 
    public void setMessage(String message) { 
        this.message = message; 
    } 
 
    // 額外的操作,方法 
    public void call(String message) { 
        System.out.println("丈夫的call:" + message); 
    } 
     
    public void look(){ 
        System.out.println("發現發廊"); 
    } 
     
    public void playDOTA(){ 
        System.out.println("這個不用解釋瞭吧~DOTA"); 
    } 
 

</span> 
 以上Bean我們將它像Web Service一樣(但是不是啊)暴露成JMX托管服務類。配置Spring文件內容如下
Java代碼 
<span style="font-size: small;"><?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> 
 
    <!– 暴露監控設備 –> 
    <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter" 
        lazy-init="false"> 
        <property name="beans"> 
            <map> 
                <entry key="bean:name=HusbandLocal" value-ref="HusbandLocal" /> 
            </map> 
        </property> 
    </bean> 
 
    <!– mbean –> 
    <bean id="HusbandLocal" class="jmx.HusbandLocal" /> 
</beans> 
</span> 
 org.springframework.jmx.export.MBeanExporter是Spring暴露管理Bean(MBean)的核心類之一。它使用一個Map類型的屬性——beans記錄要暴露MBean的類。將咱們剛剛寫的HusbandLocal以屬性註入的方式註入進去。之後寫一個加載Spring文件的main實例,開啟服務。
Java代碼 
<span style="font-size: small;">        // 加載配置文件 
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( 
                "applicationContext.xml"); 
 
        // 通過死循環保證主線程一直運行 
        while (true) { 
 
        } 
</span> 
 

 點擊進去後可以查看咱們剛才暴露的MBean,如下


 我們可以點擊MBean的操作,比如playDOTA(),後臺就調用瞭該方法。在這個界面還可以看到MBean的屬性值,你叫他們狀態也行。
如此,我們完成瞭一個本地監控MBean對象的小功能。不過就像原來說的,這有個問題就是咱們之前說的,這種本地場景不多見,不常用。Ok,咱們看看要想遠程監控需要做些什麼事情。
4.  監控遠程程序
下面我們嘗試在遠程監控咱們這個“丈夫”。
首先在Spring配置文件增加以下內容
Java代碼 
<span style="font-size: small;">    <!– 遠程連接 RMI方式–> 
    <!– 
        地址輸入 
        service:jmx:rmi://localhost/jndi/rmi://192.168.1.100:8080/myconnector 
    –> 
    <bean class="org.springframework.jmx.support.ConnectorServerFactoryBean" 
        depends-on="rmiRegistry"> 
        <property name="objectName" value="connector:name=rmi" /> 
         
        <!– 遠程連接的地址 –> 
        <property name="serviceUrl" 
            value="service:jmx:rmi://localhost/jndi/rmi://localhost:8080/myconnector" /> 
    </bean> 
     
    <!– 使用JNDI-RMI的方式進行遠程連接通訊,並且配置占用端口號 –> 
    <bean id="rmiRegistry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean"> 
        <property name="port" value="8080" /> 
    </bean></span> 
 剛才我們將我們的MBean註冊到一個基於RMI訪問方式的連接服務上(ConnectorServerFactoryBean),占用的端口是8080。這時啟用jconsole以遠程方式連接,不用輸入密碼,如下圖所示

 
之後和在本地操作一樣,可以監控MBean的屬性狀態,也可以進行相應的操作。
5.  監控Web容器
如果我們要監控一下Web服務器,比如Tomcat服務器的JVM狀態怎麼辦?這種場景非常的常見。其實配置也很簡單。我們打開{Tomcat_HOME}/bin/catalina.bat,在linux下是{Tomcat_HOME}/bin/catalina.sh文件。將原有的腳本
Java代碼 
<span style="font-size: small;">set LOGGING_MANAGER=-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager</span> 
 替換成為
Java代碼 
<span style="font-size: small;">rem 配置JMX服務端口 
set JAVA_OPTS=%JAVA_OPTS% -Dcom.sun.management.jmxremote.port=10090 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.util.logging.config.file="%CATALINA_BASE%\conf\logging.properties" 
</span> 
 
我們運行startup.bat文件,之後開啟JConsole,遠程登錄tomcat

 之後即可查看遠程Tomcat資源

 
 
而Tomcat自身這個容易也有很多模塊支持JMX規范,可以通過JConsole進行一些MBean的管理

 
6.  監控JavaEE容器
 
說完Tomcat這種Web容器,不得不說說JavaEE容器,就將開源的JBoss拉出來看看,其實JBoss自身因為是一個JavaEE容器,而JMX是屬於JavaEE5范疇內的規范,所以JBoss自身就擁有很多JMX的特性,比如咱們動態添加一個DataSource資源時候,後臺的JBoss控制臺console的界面就會自動更新運行時的狀態,數據源的連接狀態也能一覽無餘的顯示給後臺使用者。這些實際上都是JMX的特性。隻不過結合瞭Web頁面的UI罷瞭。其實基於Web頁面,大傢就能看到JBoss自身的運行狀況瞭

 如果需要JConsole連上遠端的JBoss,和Tomcat一樣,需改一下配置文件run.bat,linux的就不贅述瞭,將以下代碼段
Java代碼 
<span style="font-size: small;">if "x%JAVA_OPTS%" == "x" ( 
  set "JAVA_OPTS=-Dprogram.name=%PROGNAME%" 
) else ( 
  set "JAVA_OPTS=-Dprogram.name=%PROGNAME% %JAVA_OPTS%" 

</span> 
 
替換成
Java代碼 
<span style="font-size: small;">if "x%JAVA_OPTS%" == "x" ( 
 
  set "JAVA_OPTS=-Dprogram.name=%PROGNAME% -Dcom.sun.management.jmxremote.port=9999 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false" 
 
) else ( 
  set "JAVA_OPTS=-Dprogram.name=%PROGNAME% -Dcom.sun.management.jmxremote.port=9999 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false %JAVA_OPTS%" 

</span> 
 
之後啟動JConsole即可遠程連接JBoss,地址:192.168.1.100:9999

 
可以看出Tomcat與JBoss的消耗資源真的不是一個數量級的。
7.  總結
這次是介紹瞭JMX的使用場景和一些分佈式系統中常用的配置和監控情形,對於JMX規范本身,尤其是重要的MBean並沒有做過多的介紹,其實MBean有很多種情況,這一篇文章並不能盡述。知道他是幹什麼,遇到那些晦澀難懂的理論就不再懼怕瞭,有時間打算下次再詳細說說JMX MBean的各種使用情況。1.  JMX規范
JMX是“Java管理擴展的”的縮寫,它和其他JavaEE類似也是曾經的Sun提出的一種規范(規約),從名字上可以看出主要是負責系統管理。是一個為系統加入或者說擴展成有管理功能的規約,隻要按照這套規約行事,您的系統,某些某塊就具備被其他工具(例如JConsole)管理的能力。換句話說就是可以用JMX來監控咱們的系統運行情況,還有可以在運行時環境像Web Service、RMI一樣調用系統管理類的一些方法。實現此規范的框架也很多:Spring、Tomcat、JBoss容器……
2.  場景簡述
咱們先假設一個情景,夫妻二人。男的因為工作需要要去外地出差,因公司規定,出差不能帶傢屬,女方不能跟過去啊。所以女方給他們2個人一個手機——HTC吧。裡面有個小程序,叫做JMXImpl4Android。等到男方出差在外地瞭,在外地出差的城市,一天晚上和同事散步,路上遇到個發廊(各位男性朋友明白的啊)。此時遠在另一個城市的妻子的手機突然響瞭,手機GIS定位信息告知妻子:“您的丈夫在一個發廊門前徘徊,請註意”。妻子急瞭,立刻給丈夫打電話:“你幹嘛呢?”。丈夫戰戰栗栗,汗出如漿,乖乖的回酒店玩DOTA瞭!
我們來用Java消息擴展的視角來看看這個場景,咱們偉大一些相當於那個妻子,那個丈夫就相當於咱們的系統,出差事件相當於咱們將系統部署到瞭真正的遠程的運行環境,妻子曾HTC手機給丈夫您可以理解成把丈夫打造成具有JMX規范的系統,換句話說:此丈夫可監控。因為一個小小的GIS應用就能讓妻子隨時監控丈夫的狀態——想邪惡一把,並且還可以根據系統的狀態進行相應的措施——打電話告訴丫的別想出軌,雖然新的婚姻法下來瞭,但是房子是老娘買的,出軌?你試試!
看到這裡,大傢估計明白瞭JMX是什麼東西,幹什麼用的瞭。但是估計大傢有一個疑問,這個和Java分佈式系統有什麼關系啊?在分佈式系統中有時候我們需要監控各個分機器的狀態,比如想知道機器此時此刻的Tomcat的運行狀況如何,還可以根據狀況調用相關的操作,比如shutdown服務、去除已部署的web工程等等與服務有關的操作。或者對於調度這些節點機的主控機器也可以進行監控,在遠程使用一個JConsole調用即可。Ok,說瞭這麼多,我們看示例吧,最後再來用實例解釋JMX的那些晦澀的理論概念。
3.  監控本機程序
這種場景在實際中不太常用,對於本機的程序來說,需要監控,按需調用被托管的類方法還真不多。
相當於丈夫就在你面前,他的一舉一動都在你眼皮底下,你還需要一個Android小程序去監控他嗎?筆者使用的是Spring3的實現。所以先將Spring的包下載下來,放到項目的classpath中。
咱們先寫一個最普通的JavaBean
Java代碼 
<span style="font-size: small;">package jmx; 
 
public class HusbandLocal { 
 
    // 屬性 
    private String name; 
    private int age; 
    private String message; 
 
    // set,get 
    public String getName() { 
        System.out.println("name:"+name); 
        return name; 
    } 
 
    public void setName(String name) { 
        this.name = name; 
    } 
 
    public int getAge() { 
        System.out.println("age:"+age); 
        return age; 
    } 
 
    public void setAge(int age) { 
        this.age = age; 
    } 
 
    public String getMessage() { 
        System.out.println("message:"+message); 
        return message; 
    } 
 
    public void setMessage(String message) { 
        this.message = message; 
    } 
 
    // 額外的操作,方法 
    public void call(String message) { 
        System.out.println("丈夫的call:" + message); 
    } 
     
    public void look(){ 
        System.out.println("發現發廊"); 
    } 
     
    public void playDOTA(){ 
        System.out.println("這個不用解釋瞭吧~DOTA"); 
    } 
 

</span> 
 以上Bean我們將它像Web Service一樣(但是不是啊)暴露成JMX托管服務類。配置Spring文件內容如下
Java代碼 
<span style="font-size: small;"><?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> 
 
    <!– 暴露監控設備 –> 
    <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter" 
        lazy-init="false"> 
        <property name="beans"> 
            <map> 
                <entry key="bean:name=HusbandLocal" value-ref="HusbandLocal" /> 
            </map> 
        </property> 
    </bean> 
 
    <!– mbean –> 
    <bean id="HusbandLocal" class="jmx.HusbandLocal" /> 
</beans> 
</span> 
 org.springframework.jmx.export.MBeanExporter是Spring暴露管理Bean(MBean)的核心類之一。它使用一個Map類型的屬性——beans記錄要暴露MBean的類。將咱們剛剛寫的HusbandLocal以屬性註入的方式註入進去。之後寫一個加載Spring文件的main實例,開啟服務。
Java代碼 
<span style="font-size: small;">        // 加載配置文件 
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( 
                "applicationContext.xml"); 
 
        // 通過死循環保證主線程一直運行 
        while (true) { 
 
        } 
</span> 
 

 點擊進去後可以查看咱們剛才暴露的MBean,如下


 我們可以點擊MBean的操作,比如playDOTA(),後臺就調用瞭該方法。在這個界面還可以看到MBean的屬性值,你叫他們狀態也行。
如此,我們完成瞭一個本地監控MBean對象的小功能。不過就像原來說的,這有個問題就是咱們之前說的,這種本地場景不多見,不常用。Ok,咱們看看要想遠程監控需要做些什麼事情。
4.  監控遠程程序
下面我們嘗試在遠程監控咱們這個“丈夫”。
首先在Spring配置文件增加以下內容
Java代碼 
<span style="font-size: small;">    <!– 遠程連接 RMI方式–> 
    <!– 
        地址輸入 
        service:jmx:rmi://localhost/jndi/rmi://192.168.1.100:8080/myconnector 
    –> 
    <bean class="org.springframework.jmx.support.ConnectorServerFactoryBean" 
        depends-on="rmiRegistry"> 
        <property name="objectName" value="connector:name=rmi" /> 
         
        <!– 遠程連接的地址 –> 
        <property name="serviceUrl" 
            value="service:jmx:rmi://localhost/jndi/rmi://localhost:8080/myconnector" /> 
    </bean> 
     
    <!– 使用JNDI-RMI的方式進行遠程連接通訊,並且配置占用端口號 –> 
    <bean id="rmiRegistry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean"> 
        <property name="port" value="8080" /> 
    </bean></span> 
 剛才我們將我們的MBean註冊到一個基於RMI訪問方式的連接服務上(ConnectorServerFactoryBean),占用的端口是8080。這時啟用jconsole以遠程方式連接,不用輸入密碼,如下圖所示

 
之後和在本地操作一樣,可以監控MBean的屬性狀態,也可以進行相應的操作。
5.  監控Web容器
如果我們要監控一下Web服務器,比如Tomcat服務器的JVM狀態怎麼辦?這種場景非常的常見。其實配置也很簡單。我們打開{Tomcat_HOME}/bin/catalina.bat,在linux下是{Tomcat_HOME}/bin/catalina.sh文件。將原有的腳本
Java代碼 
<span style="font-size: small;">set LOGGING_MANAGER=-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager</span> 
 替換成為
Java代碼 
<span style="font-size: small;">rem 配置JMX服務端口 
set JAVA_OPTS=%JAVA_OPTS% -Dcom.sun.management.jmxremote.port=10090 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.util.logging.config.file="%CATALINA_BASE%\conf\logging.properties" 
</span> 
 
我們運行startup.bat文件,之後開啟JConsole,遠程登錄tomcat

 之後即可查看遠程Tomcat資源

 
 
而Tomcat自身這個容易也有很多模塊支持JMX規范,可以通過JConsole進行一些MBean的管理

 
6.  監控JavaEE容器
 
說完Tomcat這種Web容器,不得不說說JavaEE容器,就將開源的JBoss拉出來看看,其實JBoss自身因為是一個JavaEE容器,而JMX是屬於JavaEE5范疇內的規范,所以JBoss自身就擁有很多JMX的特性,比如咱們動態添加一個DataSource資源時候,後臺的JBoss控制臺console的界面就會自動更新運行時的狀態,數據源的連接狀態也能一覽無餘的顯示給後臺使用者。這些實際上都是JMX的特性。隻不過結合瞭Web頁面的UI罷瞭。其實基於Web頁面,大傢就能看到JBoss自身的運行狀況瞭

 如果需要JConsole連上遠端的JBoss,和Tomcat一樣,需改一下配置文件run.bat,linux的就不贅述瞭,將以下代碼段
Java代碼 
<span style="font-size: small;">if "x%JAVA_OPTS%" == "x" ( 
  set "JAVA_OPTS=-Dprogram.name=%PROGNAME%" 
) else ( 
  set "JAVA_OPTS=-Dprogram.name=%PROGNAME% %JAVA_OPTS%" 

</span> 
 
替換成
Java代碼 
<span style="font-size: small;">if "x%JAVA_OPTS%" == "x" ( 
 
  set "JAVA_OPTS=-Dprogram.name=%PROGNAME% -Dcom.sun.management.jmxremote.port=9999 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false" 
 
) else ( 
  set "JAVA_OPTS=-Dprogram.name=%PROGNAME% -Dcom.sun.management.jmxremote.port=9999 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false %JAVA_OPTS%" 

</span> 
 
之後啟動JConsole即可遠程連接JBoss,地址:192.168.1.100:9999

 
可以看出Tomcat與JBoss的消耗資源真的不是一個數量級的。
7.  總結
這次是介紹瞭JMX的使用場景和一些分佈式系統中常用的配置和監控情形,對於JMX規范本身,尤其是重要的MBean並沒有做過多的介紹,其實MBean有很多種情況,這一篇文章並不能盡述。知道他是幹什麼,遇到那些晦澀難懂的理論就不再懼怕瞭,有時間打算下次再詳細說說JMX MBean的各種使用情況。

作者“自我否定的勇氣,兼收並蓄的氣度”
 

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *