JMX Technology可以分成3層, 詳細的介紹可以參考 Lesson: Overview of the JMX Technology
- Instrumentation
- JMX agent
- Remote management
Instrumentation : 定義了如何實現JMX管理資源的規範。一個JMX管理資源可以是一個Java應用、一個服
務或一個設備,它們可以用Java開發,或者至少能用Java進行包裝,並且能被置入JMX
框架中,從而成為JMX的一個管理構件(Managed Bean) ,簡稱MBean。
JMX agent : Agent 是 MBean Server 的容器,主要為了管理一系列的 MBean,並且提供的一系列
服務
Remote management : JMX 可以在許多不同的方式訪問,無論是通過現有的管理協議,如SNMP或通過
專有協議等, Each adaptor provides a view through a specific protocol
of all MBeans that are registered in the MBean server. For example, an
HTML adaptor could display an MBean in a browser.
JMX 的基本部分:
MBean: 它是一個能代表管理资源的Java对象,它提供接口可以使這個class 有管理功能(如standard MBean,interface 中定義的方法使MBean具有管理功能)。
MBean server : 是管理MBean的一個java class,你需要向MBean server注册一個MBean,這個MBean才會具有管理功能。
JMX agent : agent是為了管理一系列的MBean,而提供的一系列的服務,agent可以利用Protocol adapters(例如HTTP 和SNMP)和connectors(RMI 和Jini)使不同的客户端可以访问MBean。
MBean的類型:
- Standard MBeans
- Dynamic MBeans
- Open MBeans
- Model MBeans
- MXBeans
standard MBean : standard MBean 從必须定義為Interface 然后MBean必须implements 這個interface ,
它的命名也必须遵循一定的规範,如interface為Something , MBean implement 則為
SomethingMBean.
dynamic MBean : 動態MBean是在運行期才定義它的屬性和方法,也就是說它有什麼屬性和方法
是可以動態改變的。動態MBean主要利用一些輔助類(構造函數類
MBeanConstructorInfo、屬性類MBeanAttributeInfo、方法類
MBeanOperationInfo)來完成這個功能。
open MBean : An Open MBean is just a Dynamic MBean that follows some conventions which makes
it less powerful and convenient, but more portable. Open Mbeans Tutorial
model MBean : 與標準和動態的MBean相比,你可以不用寫的MBean類,只需使用
javax.management.modelmbean.RequiredModelMBean即可。與 DynamicMBean不
同的是,DynamicMBean管理的資源一般定義在DynamicMBean中(運行時才決定管理
那些資源),而模型MBean管理的資源並不在MBean的中,而是在外部(通常是一
個類),只有在運行時,才通過一套方法將其加入到模型MBean中
(JDK 5 內建了 jmx 的 client: jconsole。只要在 jvm 啟動時加上參數: )
-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.password.file=/mypath/jmxremote.password
簡介到這邊, 接下來主要是以Spring 來設定&設計 JMX 的部份, 如果想知道基本的JMX 部份可以參考Oracle 的Tutorials Standard MBeans ,
首先設計我們的MBean , 叫ManagerMBean.java
package com.jmxBean; import org.springframework.beans.factory.DisposableBean; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ApplicationObjectSupport; import org.springframework.jmx.export.annotation.ManagedAttribute; import org.springframework.jmx.export.annotation.ManagedOperation; import org.springframework.jmx.export.annotation.ManagedResource; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; //@ManagerResource , 實例標記為由JMX管理的資源 @ManagedResource public class ManagerMBean extends ApplicationObjectSupport implements DisposableBean { private int threadPoolActiveSize; private boolean threadPoolStatus; //將getter或setter標記為JMX的屬性 @ManagedAttribute(description="check how many thread on ThreadPoolTaskExecutor is active...") public int getThreadPoolActiveSize() { return threadPoolActiveSize; } public void setThreadPoolActiveSize(int threadPoolActiveSize) { this.threadPoolActiveSize = threadPoolActiveSize; } @ManagedAttribute(description="check ThreadPoolTaskExecutor are running.") public boolean isThreadPoolStatus() { return threadPoolStatus; } public void setThreadPoolStatus(boolean threadPoolStatus) { this.threadPoolStatus = threadPoolStatus; } ///把方法標記為JMX的操作 @ManagedOperation(description = "shutdown the server") @Override public void destroy() throws Exception { ApplicationContext application = getApplicationContext(); System.out.println("Trigger command from jmx remote ..... "); // ThreadPoolTaskExecutor task = (ThreadPoolTaskExecutor) application.getBean("taskExecutor"); // System.out.println("getActiveCount = " task.getActiveCount()); } }這邊implements 的是spring 的DisposableBean , 實現org.springframework.beans.factory.DisposableBean interface 的bean 允許在容器銷毀該bean 的時候獲得一次回調,下面是相關Annotation 的說明,
Table 22.2. Source-Level Metadata Types
Purpose | Annotation | Annotation Type |
---|---|---|
Mark all instances of a Class asJMX managed resources | @ManagedResource | Class |
Mark a method as a JMX operation | @ManagedOperation | Method |
Mark a getter or setter as one half of a JMX attribute | @ManagedAttribute | Method (only getters and setters) |
Define descriptions for operation parameters | @ManagedOperationParameter and@ManagedOperationParameters | Method |
還有parameter 的設定
Table 22.3. Source-Level Metadata Parameters
Parameter | Description | Applies to |
---|---|---|
ObjectName | Used by MetadataNamingStrategy to determine the ObjectName of amanaged resource | ManagedResource |
description | Sets the friendly description of the resource, attribute or operation | ManagedResource ,ManagedAttribute ,ManagedOperation ,ManagedOperationParameter |
currencyTimeLimit | Sets the value of thecurrencyTimeLimit descriptor field | ManagedResource ,ManagedAttribute |
defaultValue | Sets the value of the defaultValue descriptor field | ManagedAttribute |
log | Sets the value of the log descriptorfield | ManagedResource |
logFile | Sets the value of the logFile descriptor field | ManagedResource |
persistPolicy | Sets the value of the persistPolicy descriptor field | ManagedResource |
persistPeriod | Sets the value of the persistPeriod descriptor field | ManagedResource |
persistLocation | Sets the value of thepersistLocation descriptor field | ManagedResource |
persistName | Sets the value of the persistName descriptor field | ManagedResource |
name | Sets the display name of an operation parameter | ManagedOperationParameter |
index | Sets the index of an operation parameter | ManagedOperationParameter |
然後我們在ApplicationContext.xml 設定如下
<?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:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> <bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"> <property name="corePoolSize" value="5" /> <property name="maxPoolSize" value="10" /> <property name="queueCapacity" value="25" /> </bean> <bean id="registry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean"> <property name="port" value="1099" /> </bean> <bean id="serverConnector" class="org.springframework.jmx.support.ConnectorServerFactoryBean"> <property name="objectName" value="connector:name=rmi" /> <property name="serviceUrl" value="service:jmx:rmi://localhost/jndi/rmi://localhost:1099/myconnector" /> <!-- Set the rmi connection user,password that is in jmxremote.password file. --> <!-- <property name="environmentMap"> <map> <entry key="jmx.remote.x.password.file" value="/mypath/jmxremote.password"> </entry> </map> </property> --> </bean> <!-- Step 1, defined MBean class (Instrumentation) --> <bean id="managerBean" class="com.jmxBean.ManagerMBean"></bean> <!-- Step 2, defined MBeanExporter class ,(JMX agent) --> <bean id="mBeanExporter" class="org.springframework.jmx.export.MBeanExporter"> <property name="assembler" ref="assembler" /> <property name="namingStrategy" ref="namingStrategy"/> <property name="autodetect" value="true"/> <!-- <property name="beans"> <map> <entry key="mbean:name=managerBean" value-ref="managerBean" /> </map> </property> --> </bean> <bean id="jmxAttributeSource" class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource" /> <bean id="assembler" class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler"> <property name="attributeSource" ref="jmxAttributeSource" /> </bean> <!-- will pick up the ObjectName from the annotation --> <bean id="namingStrategy" class="org.springframework.jmx.export.naming.MetadataNamingStrategy"> <property name="attributeSource" ref="jmxAttributeSource" /> </bean> <!-- To create MBeanServer by JSR-160 for remote (Remote Management) --> <!-- <bean id="clientConnector" class="org.springframework.jmx.support.MBeanServerConnectionFactoryBean"> <property name="serviceUrl" value="service:jmx:rmi:///jndi/rmi://localhost:1099/myconnector" /> </bean> --> <!-- Accessing MBeans via Proxies uses clientConnector --> <!-- <bean id="emailStopProxy" class="org.springframework.jmx.access.MBeanProxyFactoryBean"> <property name="objectName" value="mbean:name=managerBean" /> <property name="proxyInterface" value="org.springframework.beans.factory.DisposableBean" /> <property name="server" ref="clientConnector" /> </bean> --> </beans>
詳細說明一下整個XML的設定, 如果不是使用JDK 自帶的MBean server or web container 的話, 在Spring裡面要先register rmi , as below:
<bean id="registry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean"> <property name="port" value="1099" /> </bean>
然後再來要設定serverConnector ,ObjectName 設為rmi , spring 會自動register MBserver connector 依照ObjectName ,下面透過ConnectorServerFactoryBean 建立一個JMXconnector, 如果要設定username,password的話必須設定environmentMap屬性
<bean id="serverConnector" class="org.springframework.jmx.support.ConnectorServerFactoryBean"> <property name="objectName" value="connector:name=rmi" /> <property name="serviceUrl" value="service:jmx:rmi://localhost/jndi/rmi://localhost:1099/myconnector" /> <!-- Set the rmi connection user,password that is in jmxremote.password file. --> <!-- <property name="environmentMap"> <map> <entry key="jmx.remote.x.password.file" value="/mypath/jmxremote.password"> </entry> </map> </property> --> </bean>
然後建立我們的MBean instance
<!-- Step 1, defined MBean class (Instrumentation) --> <bean id="managerBean" class="com.jmxBean.ManagerMBean"></bean>
再來是設定MBeanExporter , Spring 裡MBeanExporter 用來將你的MBean 註冊到JMX MBeanServer上,
assembler 這邊指向一個MetadataMBeanInfoAssembler,屬性指向一個AnnotationJmxAttributeSource,看到Annotation也就知道是用jdk1.5的Annotation了。用途是将你所需要變成MBean class的信息提取出来,並生成MBean。Spring大大简化了MBean的實現方式。namingStrategy這邊reference 是 MetadataNamingStrategy , 代表會使用 source level metadata來獲得 ObjectName.
<!-- Step 2, defined MBeanExporter class ,(JMX agent) --> <bean id="mBeanExporter" class="org.springframework.jmx.export.MBeanExporter"> <property name="assembler" ref="assembler" /> <property name="namingStrategy" ref="namingStrategy"/> <property name="autodetect" value="true"/> <!-- <property name="beans"> <map> <entry key="mbean:name=managerBean" value-ref="managerBean" /> </map> </property> --> </bean>
其中mark 住的clientConnector 跟 emailStopProxy 是建立一個clientConnector 指向一個jmx rmi 的serverConnector , 再透過proxy 存取MBean , 相關設定可以參考Spring 的JMX設定,
再來透過jconsole 連線到server , 位置就是serverConnection的設定
service:jmx:rmi://localhost/jndi/rmi://localhost:1099/myconnector, as below :
連線之後就能看到ManagerMBean的information ,
Reference:
Spring Doc : 22. JMX
Trail: Java Management Extensions (JMX): Table of Contents
Quickly Exposing Spring Beans as JMX MBeans
Spring by Example : JMX
Jconsole Remote Management