Terry.Li-彬

          虛其心,可解天下之問;專其心,可治天下之學;靜其心,可悟天下之理;恒其心,可成天下之業。

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            143 隨筆 :: 344 文章 :: 130 評論 :: 0 Trackbacks

          1 Introduction
          ??? Java Management Extension (JMX) API定義于JSR 3,用于應用程序管理。這些API對于被管理的應用程序來說是本地的。也就是說,在JSR 160發布之前,如果客戶端要通過JMX來管理和監控遠程的應用程序,并沒有標準的做法。JSR 160擴展了JSR 3,提供了標準的API用于連接到支持JMX的遠程應用程序。JSR 255將會把JMX升級到2.0,并可能體現在Java 7中。
          ??? 目前JSR 160定義了基于RMI(支持RMI/JRMP 和 RMI/IIOP)的連接器,還定義了可選的JMXMP連接器,它基于TCP Socket和Java序列化機制。

          ?

          2 JMX Remoting API
          2.1 JMXServiceURL
          ??? JMXServiceURL用于標識JMXConnectorServer,它是采用以下形式的字符串:
          ??? service:jmx:<protocol>://[[[ <host>]: <port>]/ <path>]
          ??? "protocol" 指定了協議,例如:rmi、iiop、jmxmp 或者 soap。"host"、"port" 和 "path"是可選的。JMXServiceURL并不足以描述所有的用于連接到JMXConnectorServer的配置信息(例如配置 RMIClientSocketFactory 和RMIServerSocketFactory),因此在構造JMXConnectorServer 和 JMXConnector的時候,還可能需要通過一個Map實例指定其它屬性。

          ?

          2.2 JMXConnectorServer
          ??? JMXConnectorServer 是MBeanServer端的組件,它需要被關聯到MBeanServer:可以通過在創建JMXConnectorServer的時候顯式指定 MBeanServer;也可以把JMXConnectorServer(本身是一個MBean)注冊到MBeanServer中。
          ??? 在被關聯到MBeanServer之后,需要啟動JMXConnectorServer以處理客戶端的請求。同樣,如果希望停止處理客戶端的請求,那么需 要停止JMXConnectorServer。JMXConnectorServer被停止之后,不應該試圖重新啟動它,而是應該將其丟棄。
          ??? 最好通過JMXConnectorServerFactory來創建JMXConnectorServer,例如:

          Java代碼
          1. //?The?address?of?the?connector?server ??
          2. JMXServiceURL?address?=?new?JMXServiceURL("service:jmx:rmi://host");??
          3. ??
          4. //?The?environment?map,?null?in?this?case ??
          5. Map?environment?=?null;??
          6. ??
          7. //?The?MBeanServer?to?which?the?JMXConnectorServer?will?be?attached?to ??
          8. MBeanServer?server?=?MBeanServerFactory.createMBeanServer();??
          9. ??
          10. //?Create?the?JMXCconnectorServer ??
          11. JMXConnectorServer?cntorServer?=?JMXConnectorServerFactory.newJMXConnectorServer(address,?environment,?server);??
          12. ??
          13. //?Start?the?JMXConnectorServer ??
          14. cntorServer.start();??

          ??? 在以上的例子中,創建JMXConnectorServer的時候指定了MBeanServer。以下是一個將JMXConnectorServer作為MBean注冊到MBeanServer的例子:

          Java代碼
          1. //?The?address?of?the?connector ??
          2. JMXServiceURL?address?=?new?JMXServiceURL("service:jmx:rmi://host");??
          3. ??
          4. //?The?environment?map,?null?in?this?case ??
          5. Map?environment?=?null;??
          6. ??
          7. JMXConnectorServer?cntorServer?=?JMXConnectorServerFactory.newJMXConnectorServer(address,?environment,?null);??
          8. ??
          9. //?The?MBeanServer?to?which?the?JMXConnectorServer?will?be?registered?in ??
          10. MBeanServer?server?=?MBeanServerFactory.createMBeanServer();??
          11. ??
          12. //?Register?the?JMXConnectorServer?in?the?MBeanServer ??
          13. ObjectName?cntorServerName?=?ObjectName.getInstance("connectors:protocol=rmi");??
          14. server.registerMBean(cntorServer,?cntorServerName);??
          15. ??
          16. //?Start?the?JMXConnectorServer ??
          17. cntorServer.start();??
          18. ??
          19. //?An?alternative?way?to?start?the?JMXConnectorServer?via?the?MBeanServer ??
          20. server.invoke(cntorServerName,?"start",?null,?null);??
          21. ??
          22. //?Yet?another?way?to?start?the?JMXConnectorServer?via?the?MBeanServer ??
          23. Object?proxy?=?MBeanServerInvocationHandler.newProxyInstance(server,?cntorServerName,?JMXConnectorServerMBean.class,?true);??
          24. JMXConnectorServerMBean?cntorServerMBean?=?(JMXConnectorServerMBean)proxy;??
          25. cntorServerMBean.start();??

          ??? 需要注意的是,在這個例子中使用了三種不同的方式啟動JMXConnectorServer:第一種方式是直接調用cntorServer對象的 start方法;第二種方式是通過MBeanServer調用MBean的方法;第三種方式是使用了 MBeanServerInvocationHandler,它繼承自InvocationHandler,用于從MBean的管理接口向 MBeanServer中的 MBean 轉發方法調用。當調用從newProxyInstance()方法返回的代理對象上的toString()、hashCode() 和equals(Object)等方法時,這些方法調用同樣也會被轉發到MBeanServer中的MBean ,因此當且僅當 MBean 在其管理接口中聲明了這些方法時才能如此操作,否則會拋出異常。

          ?

          2.3 JMXConnector
          ?? JMXConnector是客戶端的組件,客戶端程序通過它連接到遠程的MBeanServer。客戶端可以通過JMXConnector獲得遠程 MBeanServer的MBeanServerConnection 接口,并以類似本地的方式使用它。JMXConnector還支持在遠程的MBeanServer上注冊本地或者遠程的通知監聽器,以接收來自遠程 MBeanServer的通知。
          ??? 最好通過JMXConnectorFactory來創建JMXConnector,例如:

          Java代碼
          1. //?The?address?of?the?connector?server ??
          2. JMXServiceURL?address?=?...;??
          3. ??
          4. //?The?environment?map,?null?in?this?case ??
          5. Map?environment?=?null;??
          6. ??
          7. //?Create?the?JMXCconnectorServer ??
          8. JMXConnector?cntor?=?JMXConnectorFactory.connect(address,?environment);??
          9. ??
          10. //?Obtain?a?"stub"?for?the?remote?MBeanServer ??
          11. MBeanServerConnection?mbsc?=?cntor.getMBeanServerConnection();??
          12. ??
          13. //?Call?the?remote?MBeanServer ??
          14. String?domain?=?mbsc.getDefaultDomain();??
          15. 也可以先實例化JMXConnector,然后在連接到MBeanServer,例如:??
          16. //?The?address?of?the?connector?server ??
          17. JMXServiceURL?address?=?...;??
          18. ??
          19. //?The?creation?environment?map,?null?in?this?case ??
          20. Map?creationEnvironment?=?null;??
          21. ??
          22. //?Create?the?JMXCconnectorServer ??
          23. JMXConnector?cntor?=?JMXConnectorFactory.newJMXConnector(address,?creationEnvironment);??
          24. ??
          25. //?The?connection?environment?map,?null?in?this?case ??
          26. //?May?contain?-?for?example?-?user's?credentials ??
          27. Map?connectionEnvironment?=?null;??
          28. ??
          29. //?Connect ??
          30. cntor.connect(connectionEnvironment);??
          31. ??
          32. //?Obtain?a?"stub"?for?the?remote?MBeanServer ??
          33. MBeanServerConnection?mbsc?=?cntor.getMBeanServerConnection();??
          34. ??
          35. //?Call?the?remote?MBeanServer ??
          36. String?domain?=?mbsc.getDefaultDomain();??

          ??? 需要注意的是,以上的例子中采用了兩個不同的Map對象保存相關的屬性:一個用于實例化;另外一個用于連接。MBeanServerConnection 接口在JMX 1.2中定義,用于支持remote API。由于之前版本的MBeanServer接口不能直接被客戶端使用(例如其registerMBean(), deserialize(), getClassLoader()等方法對于客戶端來說沒有意義),因此在JMX 1.2中,MBeanServer接口繼承自MBeanServerConnection接口。

          ??? RMIConnector是標準的JMXConnector。由于它使用RMI協議,因此需要一個stub object來處理RMI調用的細節。stub class通常存在于客戶端的類路徑上,但是stub object通常是從命名服務器處下載,因此RMI客戶端需要知道stub object被綁定到RMI server上的路徑。JSR 160定義了兩種獲得stub object的方式:
          ??? 第一種方式不需要命名服務器,而是將stub object編碼為JMXServiceURL的一部分,即"encoded form"。如果采用RMI/JRMP協議,那么對stub object被序列化之后的所有字節進行Base64編碼,然后將編碼后的字符添加到JMXServiceURL中,并且以/stub/開始;如果采用 RMI/ IIOP,那么IOR被添加到JMXServiceURL中,并以/ior/開始。以下是個例子:

          Java代碼
          1. //?JRMP?encoded?form ??
          2. service:jmx:rmi://localhost/stub/rO0ABXNyAC5qYXZheC5tYW5hZ2VtZW50LnJlbW90ZS5ybWkuUk1JU2VydmVySW1wbF9TdHViAAAAAAAAAAICAAB4cgAaamF2YS5ybWkuc2VydmVyLlJlbW90ZVN0dWLp/tzJi+FlGgIAAHhyABxqYXZhLnJtaS5zZXJ2ZXIuUmVtb3RlT2JqZWN002G0kQxhMx4DAAB4cHc5AAtVbmljYXN0UmVmMgAADjE2LjE5Mi4xMjAuMTI5AAANcQAAAAAAAAAIAOgIQgAAAPlXjcJugAEAeA==??
          3. ??
          4. //?IIOP?encoded?form ??
          5. service:jmx:iiop://localhost/ior/IOR:000000000000003b524d493a6a617661782e6d616e6167656d656e742e72656d6f74652e726d692e524d495365727665723a303030303030303030303030303030300000000000010000000000000068000102000000000f31362e3139322e3132302e31323900000d93000000000019afabcb0000000002578f08b80000000800000000000000000a0000000000000100000001000000200000000000010001000000020501000100010020000101090000000100010100??

          ??? 第二種方式是在JMXServiceURL中指定命名服務器和stub object被綁定到的JNDI路徑,即"JNDI form"。在JMXServiceURL中以/jndi/開始。將JNDI的相關配置傳遞給RMIConnector的方式有多種。例如URL 'rmi://namingHost:1099/jndiPath'指明命名服務器在名為'namingHost'的主機上并監聽1099端口,命名服務 器是rmiregistry,路徑是'/jndiPath'。同樣URL 'iiop://namingHost:900/jndiPath'指明命名服務器在名為'namingHost'的主機上并監聽900端口,命名服務器 是COS命名服務,路徑是'/jndiPath'。以下是個例子:

          Java代碼
          1. //?JNDI?URL?form?for?JRMP ??
          2. service:jmx:rmi://rmiHost/jndi/rmi://namingHost:1099/jndiPath??
          3. ??
          4. //?JNDI?URL?form?for?IIOP ??
          5. service:jmx:iiop://rmiHost/jndi/iiop://namingHost:900/jndiPath??

          ??? 此外,JNDI屬性也可以通過系統屬性、類路徑上的'jndi.properties'文件、在調用JMXConnector.connect(Map environment)或者JMXConnectorFactory.connect(JMXServiceURL url, Map environment)方法時傳遞的environment參數等不同方式指定。如果JNDI屬性通過這些方式指定,那么JMXServiceURL中 可以使用簡短的JNDI格式,即只指定JNDI path。以下是個例子:

          Java代碼
          1. //?JNDI?short?form?for?JRMP ??
          2. service:jmx:rmi://rmiHost/jndi/jndiPath??
          3. ??
          4. //?JNDI?short?form?for?IIOP ??
          5. service:jmx:iiop://rmiHost/jndi/jndiPath??
          6. ??
          7. //?Code?example?that?uses?the?JNDI?short?form?specifying?JNDI?properties?via?environment?Map ??
          8. //?The?JNDI?environment ??
          9. Map?environment?=?new?HashMap();??
          10. environment.put(Context.INITIAL_CONTEXT_FACTORY,?"com.sun.jndi.rmi.registry.RegistryContextFactory");??
          11. environment.put(Context.PROVIDER_URL,?"rmi://namingHost:1099");??
          12. //?The?JNDI?short?form?JMXServiceURL ??
          13. JMXServiceURL?url?=?new?JMXServiceURL("service:jmx:rmi://rmiHost/jndi/jndiPath");??
          14. //?Connect?to?the?server?side ??
          15. JMXConnector?connector?=?JMXConnectorFactory.connect(url,?environment);??

          ?

          2.4 Remote Notification
          ??? JSR 160定義的連接器可以接收到遠程MBean發送的通知。通知被傳遞的細節依賴于連接器使用的協議。要接收通知,客戶端必須要通過調用 MBeanServerConnection.addNotificationListener(...)方法來注冊一個監聽器,這個方法有兩個重載的版 本:
          ??? 第一個版本接受一個ObjectName實例作為監聽器,由于監聽器是遠程MBeanServer中的一個MBean,因此方法中的filter和handback參數必須被傳遞到遠程的MBeanServer,因此它們必須是可以被序列化的。
          ??? 另一個版本接受NotificationListener的實例作為監聽器。這個監聽器是客戶端的本地對象,而且監聽器對象不會被傳遞到遠程的 MBeanServer,因此它也不必是可以被序列化的。NotificationFilter是否被傳遞到遠程的MBeanServer取決于 connector使用的協議,handback對象不會被傳遞到遠程MBeanServer。在另一方面,遠程的MBean發送的通知必須是可以被序列 化的,因為通知會被傳遞到客戶端。以下是在遠程的MBean上注冊監聽器的例子:

          Java代碼
          1. //?The?address?of?the?connector?server ??
          2. JMXServiceURL?address?=?...;??
          3. ??
          4. //?The?JMXConnector ??
          5. JMXConnector?connector?=?JMXConnectorFactory.connect(address);??
          6. ??
          7. //?The?MBeanServerConnection?"stub" ??
          8. MBeanServerConnection?mbsc?=?connector.getMBeanServerConnection();??
          9. ??
          10. //?The?MBeanServerDelegate?emits?notifications?about?registration/unregistration?of?MBeans ??
          11. ObjectName?delegateName?=?ObjectName.getInstance("JMImplementation:type=MBeanServerDelegate");??
          12. ??
          13. NotificationListener?listener?=?new?NotificationListener()??
          14. {??
          15. ???public?void?handleNotification(Notification?notification,?Object?handback)??
          16. ???{??
          17. ??????//?Do?something??
          18. ???}??
          19. };??
          20. ??
          21. mbsc.addNotificationListener(delegateName,?listener,?null,?null);??

          ?

          3 JMX Remoting Security
          ??? JSR 160提供了一種可插拔的認證機制,它基于JMXAuthenticator接口。JMXAuthenticator接口中只包含如下一個方法,它接受從 客戶端得到的身份證明信息作為參數,返回javax.security.auth.Subject對象的一個實例。

          Java代碼
          1. public ?Subject?authenticate(Object?credentials)? throws ?SecurityException??

          ??? 以下是在JMXConnectorServer 中使用JMXAuthenticator的例子:

          Java代碼
          1. //?The?address?of?the?connector?server ??
          2. JMXServiceURL?address?=?...;??
          3. ??
          4. //?The?JMXAuthenticator?implementation ??
          5. JMXAuthenticator?authenticator?=?...;??
          6. ??
          7. //?The?environment?map ??
          8. Map?environment?=?new?HashMap();??
          9. environment.put(JMXConnectorServer.AUTHENTICATOR,?authenticator);??
          10. ??
          11. //?The?MBeanServer?to?which?the?JMXConnectorServer?will?be?attached?to ??
          12. MBeanServer?server?=?MBeanServerFactory.createMBeanServer();??
          13. ??
          14. //?Create?the?JMXCconnectorServer ??
          15. JMXConnectorServer?cntorServer?=?JMXConnectorServerFactory.newJMXConnectorServer(address,?environment,?server);??
          16. ??
          17. //?Start?the?JMXConnectorServer ??
          18. cntorServer.start();??

          ??? 以下是在JMXConnector中使用JMXAuthenticator的例子:

          Java代碼
          1. //?The?address?of?the?connector?server ??
          2. JMXServiceURL?address?=?...;??
          3. ??
          4. //?Create?the?JMXCconnectorServer ??
          5. JMXConnector?cntor?=?JMXConnectorFactory.newJMXConnector(address,?null);??
          6. ??
          7. //?The?credentials ??
          8. Object?credentials?=?...;??
          9. ??
          10. //?The?connection?environment?map ??
          11. Map?environment?=?new?HashMap();??
          12. environment.put(JMXConnector.CREDENTIALS,?credentials);??
          13. ??
          14. //?Connect?and?invoke?an?operation?on?the?remote?MBeanServer ??
          15. try ??
          16. {??
          17. ???cntor.connect(environment);??
          18. }??
          19. catch ?(SecurityException?x)??
          20. {??
          21. ???//?Uh-oh?!?Bad?credentials?!??
          22. ???throw?x;??
          23. }??
          24. ??
          25. //?Obtain?a?stub?for?the?remote?MBeanServer ??
          26. MBeanServerConnection?mbsc?=?cntor.getMBeanServerConnection();??
          27. ??
          28. //?Call?the?remote?MBeanServer ??
          29. ObjectName?delegate?=?ObjectName.getInstance("JMImplementation:type=MBeanServerDelegate");??
          30. String?id?=?mbsc.getAttribute(delegate,?"MBeanServerId");??

          ??? 當調用從JMXConnector 得到的MBeanServerConnection 接口上的方法時,最終發生在遠程MBeanServer的調用會以認證后的Subject 身份執行。如果使用SecurityManager,那么還可以為不同的Subject指定不同的權限。

          posted on 2010-09-01 22:34 禮物 閱讀(1033) 評論(0)  編輯  收藏 所屬分類: JMS
          主站蜘蛛池模板: 昌黎县| 德化县| 新安县| 伽师县| 绍兴县| 黄梅县| 浠水县| 岚皋县| 临沂市| 深泽县| 罗甸县| 肇东市| 会东县| 嘉峪关市| 宜黄县| 孝昌县| 习水县| 新闻| 弥渡县| 文水县| 额尔古纳市| 错那县| 什邡市| 安陆市| 太谷县| 司法| 南丹县| 临朐县| 江城| 吉隆县| 临江市| 延安市| 新安县| 井研县| 四子王旗| 潜江市| 平利县| 黄大仙区| 纳雍县| 昔阳县| 侯马市|