1. 程式人生 > >【Java基礎】你聽說過JMX麼

【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傳送管理或控制請求。

Adapter和Connector的區別在於:Adapter是使用某種Internet協議來與JMX Agent獲得聯絡,Agent端會有一個物件(Adapter)來處理有關協議的細節。比如SNMP Adapter和HTTP Adapter。而Connector則是使用類似RPC的方式來訪問Agent,在Agent端和客戶端都必須有這樣一個物件來處理相應的請求與應答。比如RMI Connector。
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的描述。

  1. 一個java程序裡面可以有多個不同名字的mBeanServer ,每個mbs都是一個獨立的容器,用了管理mbean
  2. 每個mbs都可以註冊多個rmi port,http port等
  3. 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