JMX入門篇_stepByStep

1 基本信息
摘要:
本篇爲JMX的學習筆記, 教你一步一步使用JMX,並提供一個能運行的完整的案例,可以使人達到快速入門的x目的。

作者:陳光耀

2 正文

      JMX(Java Management Extensions, Java管理擴展)是一個爲應用程序植入管理功能的框架。JMX是一套標準的代理和服務,實際上,用戶可以在任何Java應用程序中使用這些代理和服務實現管理。 JMX的優點在於:

      1.可以非常容易的使應用程序具有被管理的功能
      2.提供具有高度伸縮性的架構,每個JMX Agent服務可以很容易的放入到Agent中,每個JMX的實現都提供幾個核心的Agent服務,你也可以自己編寫服務,服務可以很容易的部署,取消部署。
      3.主要提供接口,允許有不同的實現。

  Jboss的成功就在於採用了JMX,從零開始、模塊化開發了Jboss服務器和容器,實現了模塊化、 嵌入式的技術架構。JMX作爲集成中心(總線),可以很方便的熱插拔新的模塊和組件。JMX服務可以通過HTTP、RMI、SNMP等多種協議進行訪問, 使其適合作爲一個網絡管理、監控平臺的技術架構。

  JDK5已經內置了JMX的API,並且JVM中包含了一個平臺級MBean Server和供管理應用使用的平臺級MXBeans,並提供了一個圖形化jmx管理和監控工具來管理JMX組件。

JMX的技術架構如下:

一. 基本概念

  JMX涉及到以下基本概念。

MBean:暴露用來操作和訪問被管資源的管理接口的java對象
MBean Server:管理一組MBean的java類,類似一個查找Mbean的註冊表,暴露出所有註冊過的Mbean的管理接口,以及提供查找Mbean和通知監聽器的方法。
MBean Agent:提供管理MBean的服務的一個Java進程,是MBean Server的容器。提供這些服務:建立MBean關係、動態加載類、簡單監控服務、定時器等。
MBean Agent可以指望有一組協議適配器(Adaptor)或連接器(Connector),使遠程客戶和不同客戶使用agent。協議適配器和連接器通常也是MBean。
協議適配器(Adaptor)或連接器(Connector):在MBean Agent之中的一些對象,用來將Agent暴露給管理應用和協議。
Adaptor和Connector區別: Adaptor通常要監聽進來的信息,這些信息是在某個協議如HTTP或SNMP中構造的。在這個意義上,協議適配器在任何時間都存在於Agent中並只 有一個組件。Connector由兩個組件組成,一個在Agent端,一個在客戶端。客戶使用客戶端連接器組件和服務器端連接器組件聯繫並和Agent通 訊。

  下圖爲RMI Connector的兩個組件通訊情況:

管理應用:連接任意數量MBean Agent的用戶應用。
JMX Agent可以通過定製開發適配器或連接器,和一個非jmx管理應用進行交互。
通知(Notification):由MBean或MBean Server發出的,封裝了事件、警告和通用信息的Java對象。MBean或Java對象可以註冊爲監聽者來接收通知。JMX的通知模型類似於Java的事件模型。
設備(Instrumentation):使用MBean或一組MBean暴露管理資源的進程。
管理應用(Manager Appliction):使用MBean的管理應用程序。

二、JMX的三層架構

分佈層(Distributed Layer):包含了能使管理應用和JMX Agent通訊的組件
代理層(Agent Layer):包含了Agents和MBean Server
裝備層(Instrument Layer):包含了可以代表可管理資源的MBean

1、分佈層:jmx的最外層,負責向外界提供jmx的agent。

  有兩種類型的分佈式交互(interaction),即建立一個連接(Connectin):
1) 通過Adaptor獲取的交互方式:通過不同的協議如HTTP,SNMP提供到MBean的可見性(visibility)。
2) JMX Agent有Connector組件,將agent的API暴露給其他分佈式技術,如RMI。


當遠程客戶端通過Adaptor或Connector和Agent建立連接後,就可以和agent中註冊的MBean進行交互。接着就進入了代理層。

2、代理層:

代理層的主要組件是MBean Server,作爲MBean的登記處,是代理層的核心。
代理層提供4個代理服務來更方便地管理MBean:定時器、監控、動態MBean 加載、關係服務。
代理層提供從管理應用到被管理資源的訪問。
Jmx代理可以運行在管理資源的機器上的JVM中,也可以位於在遠程。agent不需要知道它暴露出的資源的信息,或使用MBean的管理應用。
agent擔當了一個服務的角色,用來處理MBean,允許通過暴露出的Connector或Adaptor的一系列協議來操作MBean。

3、裝備層:離被管理資源最近的一層。由註冊在Agent上的MBean組成。

每個MBean暴露一個底層資源的一塊配置和功能,並通過一個Java對象來提供。如果底層資源不使用Java, 則MBean充當一個翻譯器。
MBean是一個輕量級的類,知道如何使用、獲取操作其資源,並向agent和用戶提供訪問途徑和功能。

使用JMX作爲應用程序架構:

  jmx 代理層用來構件應用很理想。MBean Server可以用作應用組件,如數據層、日誌組件、事務管理器的骨架。

  使用這種架構,開發人員可以很容易地從服務器中增加、改變、刪除應用服務。

三、 Getting Started:簡單MBean

  運行本文程序需要在JDK5.x環境下,並且要到 java.sun.com網站上去下載Sun的JDMK5.1(Java Dynamic Management Kit 5.1),下載後解壓,將lib目錄下的jdmktk.jar文件加到項目的類路徑上即可(如果找不到,可以向我索取 [email protected] )。

  1. 定義接口4. 運行
在IE中打入http://localhost:9092/

  1. package jmxbook.ch2;
  2.  
  3. public interface HelloWorldMBean {
  4. public void setGreeting(String greeting);
  5.  
  6. public String getGreeting();
  7.  
  8. public void printGreeting();
  9. }

2. 編寫Mbean實現類

  1. package jmxbook.ch2;
  2.  
  3. public class HelloWorld implements HelloWorldMBean {
  4. private String greeting=null;
  5.  
  6. public HelloWorld() {
  7. this.greeting="I'm a standard MBean";
  8. }
  9.  
  10. public HelloWorld(String greeting) {
  11. this.greeting=greeting;
  12. }
  13.  
  14. public String getGreeting() {
  15. return greeting;
  16. }
  17.  
  18. public void printGreeting() {
  19. System.out.println(greeting);
  20. }
  21.  
  22. public void setGreeting(String greeting) {
  23. this.greeting=greeting;
  24. }
  25. }

3. 編寫Agent

  1. package jmxbook.ch2;
  2.  
  3. import javax.management.MBeanServer;
  4. import javax.management.MBeanServerFactory;
  5. import javax.management.ObjectName;
  6. import com.sun.jdmk.comm.HtmlAdaptorServer;
  7.  
  8. public class HelloAgent {
  9. private MBeanServer server = null;
  10.  
  11. public HelloAgent() {
  12. server = MBeanServerFactory.createMBeanServer("HelloAgent");
  13.  
  14. HtmlAdaptorServer adapter = new HtmlAdaptorServer();
  15.  
  16. HelloWorld hw = new HelloWorld();
  17.  
  18. ObjectName adapterName = null;
  19. ObjectName mbeanName = null;
  20.  
  21. try {
  22. mbeanName = new ObjectName("HelloAgent:name=helloWrold");
  23. server.registerMBean(hw, mbeanName);
  24.  
  25. adapterName = new ObjectName(
  26. "HelloAgent:name=htmlAdaptor,port=9092");
  27. adapter.setPort(9092);
  28. server.registerMBean(adapter, adapterName);
  29. adapter.start();
  30.  
  31. } catch (Exception e) {
  32. e.printStackTrace();
  33. }
  34.  
  35. }
  36.  
  37. public static void main(String args[]) {
  38. System.out.println("HelloAgent is running");
  39. HelloAgent agent = new HelloAgent();
  40. }
  41. }

說明:
1) 區分Mbean: 使用ObjcetName對象,分兩部分:1) 域名 2) key-value對列表
如 HelloAgent:name=helloWorld

兩個ObjectName的相等:
ObjectName objName1=new ObjectName(“HelloAgent:name=helloWorld,type=typeA”);
ObjectName objName2=new ObjectName(“HelloAgent: type=typeA,name=helloWorld”);

則objName1.equals(objName2)返回true.

2) ObjectName衝突: MBean Server註冊兩個相同ObjectName的MBean會拋出異常.

5.使用html客戶端訪問jmx agent:

1) Agent View: 顯示所有註冊的MBean

2) MBean View: 顯示一個MBean信息

3) Admin View: 管理MBean,註冊和取消註冊MBean

  輸入key和java className, action選擇Constrctors, 可以查看類的構造函數列表(需要MBean的接口命名爲 名稱+MBean, 如HelloWorldMBean), 輸入構造函數的參數(有的話),按create可以建立新的MBean並註冊到agent.

四.使用通知:

  jmx可以使用通知機制,從一個MBean發送通知給另一個MBean,如下圖:


使用通知的步驟如下:
1) 建立通知發送者:
兩種方式:
(1) 實現javax.management.NotificationBroadcaster接口
(2) 擴展 javax.management.NotificationBroadcasterSupport類

改造HelloWorld.java

  1. package jmxbook.ch2.notification;
  2.  
  3. import javax.management.Notification;
  4. import javax.management.NotificationBroadcasterSupport;
  5.  
  6. public class HelloWorld extends NotificationBroadcasterSupport
  7. implements HelloWorldMBean {
  8. public HelloWorld() {
  9. this.greeting = "I'm a Notification Sender";
  10. }
  11.  
  12. public HelloWorld(String greeting) {
  13. this.greeting = greeting;
  14. }
  15.  
  16. public void setGreeting(String greeting) {
  17. this.greeting = greeting;
  18. Notification notification = new Notification(
  19. "jmxbook.ch2.helloWorld.test", this, -1, System
  20. .currentTimeMillis(), greeting);
  21. sendNotification(notification);
  22. }
  23.  
  24. public String getGreeting() {
  25. return greeting;
  26. }
  27.  
  28. public void printGreeting() {
  29. System.out.println(greeting);
  30. }
  31.  
  32. private String greeting;
  33. }

2) 建立通知接收者:
接口: MyListenerMBean.java:

  1. package jmxbook.ch2.notification;
  2.  
  3. import javax.management.NotificationListener;
  4.  
  5. public interface MyListenerMBean extends NotificationListener {
  6. public void printInfo(String message);
  7. }


實現類: MyListener.java

  1. package jmxbook.ch2.notification;
  2.  
  3. import javax.management.Notification;
  4.  
  5. public class MyListener implements MyListenerMBean {
  6.  
  7. public void printInfo(String message) {
  8. System.out.println(message);
  9. }
  10.  
  11. public void handleNotification(Notification notification, Object handback) {
  12. this.printInfo("My listener recieve Nofitication: " + notification.getType() + " "
  13. + notification.getMessage());
  14. }
  15. }

3) 改造HelloAgent:

  1. package jmxbook.ch2.notification;
  2.  
  3. import javax.management.*;
  4. import com.sun.jdmk.comm.HtmlAdaptorServer;
  5.  
  6. public class HelloAgent implements NotificationListener {
  7. private MBeanServer mbs = null;
  8.  
  9. public HelloAgent() {
  10. mbs = MBeanServerFactory.createMBeanServer("HelloAgent");
  11. HtmlAdaptorServer adapter = new HtmlAdaptorServer();
  12.  
  13. HelloWorld hw = new HelloWorld();
  14. ObjectName adapterName = null;
  15. ObjectName helloWorldName = null;
  16. try {
  17. adapterName = new ObjectName(
  18. "HelloAgent:name=htmladapter,port=9092");
  19. mbs.registerMBean(adapter, adapterName);
  20. adapter.setPort(9092);
  21. adapter.start();
  22.  
  23. MyListener listener = new MyListener();
  24. mbs.registerMBean(listener, new ObjectName(
  25. "HelloAgent:name=myListener"));
  26.  
  27. helloWorldName = new ObjectName(
  28. "HelloAgent:name=helloWorld,notification=yes");
  29. mbs.registerMBean(hw, helloWorldName);
  30. hw.addNotificationListener(this, null, null);
  31. hw.addNotificationListener(listener, null, null);
  32. } catch (Exception e) {
  33. e.printStackTrace();
  34. }
  35. }// constructor
  36.  
  37. public void handleNotification(Notification notif, Object handback) {
  38. System.out.println("My listener recieve Nofitication: "
  39. + notif.getType() + " " + notif.getMessage());
  40. }
  41.  
  42. public static void main(String args[]) {
  43. HelloAgent agent = new HelloAgent();
  44. System.out.println("HelloAgent is running");
  45. }
  46. }

4) 運行:
調用HelloWorld的greeting(“Can I help you?”)方法, 控制檯顯示:
Agent recieve Nofitication: jmxbook.ch2.helloWorld.test Can I help you?
My listener recieve Nofitication: jmxbook.ch2.helloWorld.test Can I help you?

五.使用RMI Connector:

1) 改造Agent:

  1. package jmxbook.ch3;
  2.  
  3. import com.sun.jdmk.comm.*;
  4. import javax.management.*;
  5.  
  6. public class JMXBookAgent {
  7. private MBeanServer server = null;
  8.  
  9. public JMXBookAgent() {
  10. System.out.println("\n\tCREATE the MBeanServer.");
  11. server = MBeanServerFactory.createMBeanServer("JMXBookAgent");
  12. startHTMLAdapter();
  13. startRMIConnector();
  14. }
  15.  
  16. protected void startHTMLAdapter() {
  17. HtmlAdaptorServer adapter = new HtmlAdaptorServer();
  18. ObjectName adapterName = null;
  19. try {
  20. adapter.setPort(9092);
  21. adapterName = new ObjectName("JMXBookAgent:name=html,port=9092");
  22. server.registerMBean(adapter, adapterName);
  23. adapter.start();
  24. } catch (Exception e) {
  25. ExceptionUtil.printException(e);
  26. System.out.println("Error Starting HTML Adapter for Agent");
  27. }
  28. }
  29.  
  30. protected void startRMIConnector() {
  31. RmiConnectorServer connector = new RmiConnectorServer();
  32. ObjectName connectorName = null;
  33. try {
  34. connector.setPort(2099);
  35. connectorName = new ObjectName("JMXBookAgent:name=RMIConnector");
  36. server.registerMBean(connector, connectorName);
  37. connector.start();
  38. } catch (Exception e) {
  39. ExceptionUtil.printException(e);
  40. }
  41. }
  42.  
  43. public static void main(String[] args) {
  44. System.out.println("\n~~~~~~~~~~~~~~~~~~~~~~~"
  45. + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
  46. System.out.println("\n>>> START of JMXBook Agent");
  47. System.out.println("\n>>> CREATE the agent...");
  48. JMXBookAgent agent = new JMXBookAgent();
  49. System.out.println("\nAgent is Ready for Service...\n");
  50. }
  51. }


2) 添加異常顯示類

  1. package jmxbook.ch3;
  2.  
  3. import javax.management.*;
  4.  
  5. public class ExceptionUtil {
  6. public static void printException(Exception e) {
  7. System.out.println("-------[ Exception ]-------");
  8. e.printStackTrace();
  9. if (e instanceof MBeanException) {
  10. boolean hasEmbeddedExceptions = true;
  11. Exception embeddedExc = e;
  12. while (hasEmbeddedExceptions) {
  13. embeddedExc = ((MBeanException) embeddedExc)
  14. .getTargetException();
  15. System.out.println("-------[ Embedded Exception ]-------");
  16. embeddedExc.printStackTrace();
  17. if (!(embeddedExc instanceof MBeanException)) {
  18. hasEmbeddedExceptions = false;
  19. }
  20. }
  21. }
  22. }
  23. }

3) RMI 工廠

  1. package jmxbook.ch3;
  2.  
  3. import com.sun.jdmk.comm.RmiConnectorAddress;
  4. import com.sun.jdmk.comm.RmiConnectorClient;
  5.  
  6.  
  7. public class RMIClientFactory {
  8. public static RmiConnectorClient getClient() {
  9. RmiConnectorClient client = new RmiConnectorClient();
  10. RmiConnectorAddress address = new RmiConnectorAddress();
  11. address.setPort(2099);
  12. System.out.println("\t\tTYPE\t= " + address.getConnectorType());
  13. System.out.println("\t\tPORT\t= " + address.getPort());
  14. System.out.println("\t\tHOST\t= " + address.getHost());
  15. System.out.println("\t\tSERVER\t= " + address.getName());
  16. try {
  17. client.connect(address);
  18. } catch (Exception e) {
  19. ExceptionUtil.printException(e);
  20. }
  21. return client;
  22. }
  23. }

5) 建立RMI客戶端:

  1. package jmxbook.ch3;
  2.  
  3. import javax.management.*;
  4. import jmxbook.ch2.*;
  5. import com.sun.jdmk.comm.*;
  6.  
  7. public class MBeanSetup {
  8. public MBeanSetup() {
  9. try {
  10. RmiConnectorClient client = RMIClientFactory.getClient();
  11. ObjectName hwName = new ObjectName("JMXBookAgent:name=helloWorld");
  12. client.createMBean("jmxbook.ch2.HelloWorld", hwName);
  13. client.invoke(hwName, "printGreeting", null, null);
  14. } catch (Exception e) {
  15. e.printStackTrace();
  16. }
  17. }
  18.  
  19. public static void main(String args[]) {
  20. MBeanSetup setup = new MBeanSetup();
  21. }
  22. }

6) 運行:
運行agent:

  1. java -cp ..\lib\jdmkrt.jar;. jmxbook.ch3.JMXBookAgent
  2.  
  3. >>> START of JMXBook Agent
  4.  
  5. >>> CREATE the agent...
  6.  
  7. CREATE the MBeanServer.
  8.  
  9. Agent is Ready for Service...

運行客戶端:

  1. java -cp ..\lib\jdmkrt.jar;. jmxbook.ch3.MBeanSetup
  2.  
  3. TYPE = SUN RMI
  4. PORT = 2099
  5. HOST = chengy
  6. SERVER = name=RmiConnectorServer
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章