你聽說過JMX么


什么是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還有消息發布和訂閱功能。需要使用時可以參考。

參考


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM