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的各種使用情況。
作者“自我否定的勇氣,兼收並蓄的氣度”