【Java基礎】你聽說過JMX麼
目錄
- 什麼是JMX
- 相關概念
- MBean程式碼示例
- MBean本地連線
- MBean遠端連線
- 通過Spring釋出MBean
- 訊息訂閱釋出
- 參考
什麼是JMX
JMX(Java管理擴充套件),是一套給應用程式引入監控管理功能的介面。比如我們可以通過JMX來監控Tomcat的執行狀態。JMX最主要的應用場景就是中介軟體的監控,配置檔案的線上修改配置。
相關概念
一個典型的JMX架構圖:
MBean:是Managed Bean的簡稱。在JMX中MBean代表一個被管理的資源例項,通過MBean中暴露的方法和屬性,外界可以獲取被管理的資源的狀態和操縱MBean的行為。事實上,MBean就是一個Java Object,同JavaBean模型一樣,外界使用自醒和反射來獲取Object的值和呼叫Object的方法,只是MBean更為複雜和高階一些。
MBeanServer:MBean生存在一個MBeanServer中。MBeanServer管理這些MBean,並且代理外界對它們的訪問。並且MBeanServer提供了一種註冊機制,是的外界可以通過名字來得到相應的MBean例項。
JMX Agent:Agent只是一個Java程序,它包括這個MBeanServer和一系列附加的MbeanService。當然這些Service也是通過MBean的形式來發布。
ObjectName:MBean在MBeanServer中的唯一標識。
Protocol Adapters and Connectors
JMX Agent通過各種各樣的Adapter和Connector來與外界(JVM之外)進行通訊。同樣外界(JVM之外)也必須通過某個Adapter和Connector來向JMX Agent傳送管理或控制請求。
JMX Agent可以帶有任意多個Adapter,因此可以使用多種不同的方式訪問Agent。
jmx中的三層結構:
Instrumentation 層:Instrumentation層主要包括了一系列的介面定義和描述如何開發MBean的規範。通常JMX所管理的資源有一個或多個MBean組成,因此這個資源可以是任何由Java語言開發的元件,或是一個JavaWrapper包裝的其他語言開發的資源。
Agent 層:Agent用來管理相應的資源,並且為遠端使用者提供訪問的介面。Agent層構建在Intrumentation層之上,並且使用並管理Instrumentation層內部描述的元件。通常Agent由一個MBeanServer和多個系統服務組成。另外Agent還提供一個或多個Adapter或Connector以供外界的訪問。
JMX Agent並不關心它所管理的資源是什麼。
Distributed 層:Distributed層關心Agent如何被遠端使用者訪問的細節。它定義了一系列用來訪問Agent的介面和元件,包括Adapter和Connector的描述。
- 一個java程序裡面可以有多個不同名字的mBeanServer ,每個mbs都是一個獨立的容器,用了管理mbean
- 每個mbs都可以註冊多個rmi port,http port等
- platformMBeanServer 是由jvm建立的,並添加了一些系統的mbean,如cpu,記憶體,網路,執行緒等等
MBean程式碼示例
一個MBean是一個被管理的Java物件,有點類似於JavaBean,一個裝置、一個應用或者任何資源都可以被表示為MBean,MBean會暴露一個介面對外,這個介面可以讀取或者寫入一些物件中的屬性,通常一個MBean需要定義一個介面,以MBean結尾, 例如: EchoMBean, 格式為XXXMBean,這個是規範,必須得遵守。
import javax.management.MBeanServer;
import javax.management.ObjectName;
import java.lang.management.ManagementFactory;
public class App {
public static void main(String[] args) throws Exception {
// 建立MBeanServer
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
// 新建MBean ObjectName, 在MBeanServer裡標識註冊的MBean
ObjectName name = new ObjectName("com.csx.demo.spring.boot.jmx.mbean:type=Echo");
// 建立MBean,Echo類需要實現相關介面
Echo mbean = new Echo();
//註冊以後可以通過Jconsole等工具檢視
// 在MBeanServer裡註冊MBean, 標識為ObjectName(com.dxz.mbean:type=Echo)
mbs.registerMBean(mbean, name);
// 在MBeanServer裡呼叫已註冊的EchoMBean的print方法
mbs.invoke(name, "print", new Object[] { "china sf"}, new String[] {"java.lang.String"});
Thread.sleep(Long.MAX_VALUE);
}
}
通過上面程式碼釋出Echo後,我們就可以通過Jconsole等工具檢視Echo在JMX上的註冊情況了。
MBean本地連線
當我們啟動java程序後,經常會使用jps,jinfo,jmap,jstat等jdk自帶的命令去查詢程序的狀態,這其中的原理就是,當java程序啟動後,會建立一個用於本機連線的“localConnectorAddress”放到當前使用者目錄下,當使用jps等連線時,會到當前使用者目錄下取到“localConnectorAddress”這個JMX連線地址並連線。
MBean遠端連線
若想遠端連線訪問,肯定需要mBeanServer註冊一個或多個埠,如rmi埠,http埠等。有兩種方法可以配置遠端連線:
一種是直接在程式碼裡面指定rmi埠,並繫結,此種方法需要使用客戶端程式碼訪問,
另一種程式碼不用指定埠,只需要把mbean註冊到platformMBeanServer 裡面,並在啟動程序時加jmx引數指定,用這種方法可以通過jconsole,jvisualvm遠端訪問。比如Tomcat的監控配置
-Dcom.sun.management.jmxremote=true 相關 JMX 代理偵聽開關
-Djava.rmi.server.hostname 伺服器端的IP
-Dcom.sun.management.jmxremote.port=29094 相關 JMX 代理偵聽請求的埠
-Dcom.sun.management.jmxremote.ssl=false 指定是否使用 SSL 通訊
-Dcom.sun.management.jmxremote.authenticate=false 指定是否需要密碼驗證
通過Spring釋出MBean
一些概念:
MBeanExporter: 從字面上很容易理解, 用來將一些spring的bean作為MBean暴露給MBEanServer。
MBeanServerFactoryBean: 也可以在spring中作為一個spring bean注入, 它用來將外部或者當前機器上的MBeanServer包裝成一個bean。
MBeanInfoAssembler : 用來控制作為MBean的spring bean的哪些屬性或方法將暴露出去, 以及決定何種形式的bean會被暴露成MBean. 不同的實現有不同的暴露方式。
ObjectNamingStrategy : 用來控制作為MBean暴露出去的spring bean在MBeanServer中將如何命名(ObjectName), 描述, 指定初始值等, ObjectName通常採用"域:鍵=值,鍵=值,...".
ConnectorServerFactoryBean : 用來給外界訪問當前spring中的MBeanServer bean提供一個聯結器, 也就是給MBeanServer開一個外加訪問的口子, 比如"service:jmx:jmxmp://localhost:9875" 讓外界通過jmxmp協議, 通過9875埠來訪問MBeanServer, 外界要訪問MBeanServer, 必須提供一個connector. 預設聯結器是jmxmp協議service:jmx:jmxmp://localhost:9875 , 也可以通過其他協議的聯結器, 比如協議RMI,IIOP, Burlap,Hessian,SOAP
MBeanServerConnectionFactoryBean: 用來建立一個訪問MBeanServer的客戶端聯結器, 比如MBeanServer bean暴露了一個伺服器端聯結器, 那麼客戶端就可以通過這個聯結器來訪問MBeanServer中的MBean. 可以理解為ConnectorServerFactoryBean的對應物, server與client之間就是這兩種聯結器建立通訊連線
MBeanProxyFactoryBean: 用來建立客戶端訪問遠端MBeanServer中的MBean的代理, 客戶端要訪問伺服器端的bean, 除了客戶端聯結器之外, 還需要一個代理, 相當於一個伺服器端的stub.
//將SpittleController匯出為MBean
@ManagedResource(objectName="spitter:name=SpittleController3")
public class SpittleCntroller3 {
// 預設每個頁面的大小
public static final int DEFAULT_SPITTLES_PER_PAGE = 25;
// 每頁的大小
private int spittlesPerPage = DEFAULT_SPITTLES_PER_PAGE;
//@ManagedOperation@ManagedOperation註解替換@ManagedAttribute註解來標註存取器方法
@ManagedAttribute //將spittlesPerPage暴露為託管屬性
public int getSpittlesPerPage() {
return spittlesPerPage;
}
//@ManagedOperation@ManagedOperation註解替換@ManagedAttribute註解來標註存取器方法
@ManagedAttribute //將spittlesPerPage暴露為託管屬性
public void setSpittlesPerPage(int spittlesPerPage) {
this.spittlesPerPage = spittlesPerPage;
}
@RequestMapping(value = "/test3", method = GET)
public String test() {
String result = spittlesPerPage + " - test()";
System.out.println(result);
return "home";
}
}
@ManagedResource將類暴露成MBean,@ManagedAttribute暴露屬相,@ManagedOperation暴露方法。上面的配置需要開啟@EnableMBeanExport註解。
遠端MBean的暴露和訪問方法請參考部落格
訊息訂閱釋出
另外JMX還有訊息釋出和訂閱功能。需要使用時可以參考。
參考
https://www.cnblogs.com/duanxz/category/689081.html
http://www.cnblogs.com/dongguacai/p/5900507.html
https://www.imooc.com/article/37008?block_id=tuijian_wz
https://blog.csdn.net/lmy86263/article/details/7103