天天看點

Java進階開發必備技能之JMX監控JMX監控java項目内容 之 标準MBeanJMX監控java項目内容 之 MXBean

文章目錄

  • JMX監控java項目内容 之 标準MBean
    • 第一步:編寫MBean接口和對應的實作類
    • 第二步:建立對應的jmx代理并将mbean注冊到代理中
    • 第三步:檢視MBean資料
  • JMX監控java項目内容 之 MXBean

JMX監控java項目内容 之 标準MBean

JMX是Java Management Extensions 的簡寫,即Java管理擴充.

通過JMX,我們可以監控的内容包括:

1、伺服器中各種資源的使用情況:如CPU、記憶體等
2、JVM記憶體使用情況
3、JVM中的線程情況
4、JVM中加載的類
           

JMX技術可以被分為3層,如下:

* 監測(Instrumentation)
* JMX代理
* 遠端管理
           

圖檔如下:

Java進階開發必備技能之JMX監控JMX監控java項目内容 之 标準MBeanJMX監控java項目内容 之 MXBean

監控層的作用就是使用MBean來監控我們關心的性能名額。因為通常關注的性能名額比較多,通常情況下,在監控層我們會有多個MBean,每個MBean監控一類資訊。

JMX代理相當于一個容器,所有的MBean都注冊到這個容器中。這個容器可以接受外部的請求,傳回MBean的監控資訊。當我們想從遠端擷取某個MBean的檢測資訊,我們就給這個容器發送一個請求,由這個容器将這個MBean的檢測資訊傳回給我們。JMX代理的核心元件是MBean server,它是一個被管理對象的伺服器,MBeans在其中注冊。一個JMX代理還包括一組用于管理MBeans的服務和至少一個通信擴充卡(adaptor)或連接配接器(connector) 以供管理程式通路。

使用一個遠端用戶端連接配接MBean Server來擷取MBean的監控資訊。

JMX規範定義了5種MBean:
	1.	标準MBeans
	2.	動态MBeans
	3.	Open MBeans
	4.	Model MBeans
	5.	MXBeans
           

但是對于我們日常需要監控的資料,我們隻需要編碼方式比較簡單的标準MBeans即可,這種方式傳回的都是基本的資料類型。

下面講解标準MBean的編寫方式和規範

要有一個叫xxxMBean的接口,然後繼承這個MBean接口的類名必須是xxx類,否則無法注冊到jmx代理中。

第一步:編寫MBean接口和對應的實作類

實作類

public class Test implements TestMBean {

   private String name = "你好啊";

   public String getName() {
	  return name;
   }

   public void setName(String name) {
	  this.name = name;
   }

   @Override
   public String printHello() {
	  String name = "你好!";
	  return  name;
   }

   @Override
   public String printTestParams(String param) {
	  return param;
   }

}
           

接口

public interface TestMBean {

   public String printHello();

   public String printTestParams(String param);

}
           

上述代碼中的第二種方法可以通過修改傳參來擷取到對應的資料!

第二步:建立對應的jmx代理并将mbean注冊到代理中

public static void main(String[] args) throws Exception {

   MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
   ObjectName name = new ObjectName("com.game.jmx.mbean:type=Test");
   Test mbean = new Test();
   mbs.registerMBean(mbean, name);

   System.out.println("Waiting forever...");
   Thread.sleep(Long.MAX_VALUE);
}
           

若是要啟動遠端連接配接此時就需要定義一個IP和端口

/**
 * 開啟JMX監控
 *
 * @throws Exception
 */
public void startJmx(int port) {
   try {
	  String ip = InetAddress.getLocalHost().getHostAddress();//獲得本機IP
	  LocateRegistry.createRegistry(port);
	  JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + ip + ":" + port + "/jmxrmi");
	  JMXConnectorServer ser = JMXConnectorServerFactory.newJMXConnectorServer(url, null, server);
	  ser.start();
   } catch (Exception e) {
	  JmxMgr.log.error("啟動jmx錯誤,{}", e);
   }
}
           

上述代碼中的server就是MBeanServer。

ps:要開啟遠端監控的方式需要配置如下

如果隻是本地類測試,隻需要配置端口和ip即可

若要遠端監控需要配置

找到檔案 /tomcat/bin/catalina.sh
找到下面的内容
# —– Execute The Requested Command —————————————–
在其上,添加以下配置


authenticate,true 開啟鑒權功能
access.file,權限檔案路徑
password.file,密碼檔案路徑

将 JAVA_HOME/jre/lib/management 下面的 jmxremote.access 和jmxremote.password.template 拷貝到 tomcat conf目錄下
1:jmxremote.password.template檔案名修改為jmxremote.password。
2:修改兩個檔案的權限
chmod 600 jmxremote.access
chmod 600 jmxremote.password
           

第三步:檢視MBean資料

此時jmx代理也編寫完畢,此時就有兩種方式來檢視MBean對應的資訊

第一種方式就是直接的打開Jconsole或者Jvisulevm來檢視對應的mbean

第二種方式就是編碼連接配接到jmx代理然後進行檢視

這裡說一下第二種方式

連接配接到jmx伺服器

/**
 * 用戶端連結到遠端jmx伺服器
 */
public static MBeanServerConnection connectJmx(int jmxPort) {
   MBeanServerConnection mbsc = null;
   try {
	  //連結到遠端JMX
	  String jmxAddress = InetAddress.getLocalHost().getHostAddress();//獲得本機IP,遠端的就是遠端機器的IP位址
	  JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + jmxAddress + ":" + jmxPort + "/jmxrmi");
	  JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
	  mbsc = jmxc.getMBeanServerConnection();
   } catch (Exception e) {
	  log.error("連結jmx伺服器失敗,錯誤{}", e);
   }
   return mbsc;
}
           

上述代碼可以擷取到對應的jmx遠端連接配接,此時可以通過遠端連接配接到操作對應的mbean了

如下:

//建構要查詢的類
ObjectName objectName = new ObjectName("gs:name=com.server.game.jmx.mbean.Test");
MBeanInfo mBeanInfo = mbsc.getMBeanInfo(objectName);

//擷取MBean的方法
TestMBean testMBean = MBeanServerInvocationHandler.newProxyInstance(mbsc, objectName, TestMBean.class, false);
String s = testMBean.printHello();

System.out.println(s);
           

擷取記憶體的資料

//擷取記憶體的使用情況
MemoryMXBean memBean = ManagementFactory.newPlatformMXBeanProxy(mbsc, ManagementFactory.MEMORY_MXBEAN_NAME, MemoryMXBean.class);
MemoryUsage heap = memBean.getHeapMemoryUsage();
//堆使用情況
long used = heap.getUsed();
long committed = heap.getCommitted();
           

至此,一個基于标準MBean的jmx監控就開發完畢了。

當然jmx的監控也沒有這麼簡單,其中還有MBean與Mbean之間的通知的機制,同時也有其他動态的MBean,此種MBean的方式可以傳回比較複雜的資料結構,不想MBean隻能傳回基本的資料類型。

昨天老大又說要傳回一個對象!此刻,懵逼了!好吧,繼續研究JMX!

JMX監控java項目内容 之 MXBean

jmx可以傳回對象這種複雜的資料類型,這個叫MXBean 。 前提是傳回的對象的父類中不能有Abstract類,否則會報錯。報錯的如下

javax.management.NotCompliantMBeanException: 
com.server.game.jmx.mxbean.map.MapInfoMXBean:
Method com.server.game.jmx.mxbean.map.MapInfoMXBean.getMServer has parameter 
or return type that cannot be translated into an open type

注冊MBean的時候報錯,其實就是在對傳回的對象進行内省的時候判斷不是接口而是Abstract就包上述錯誤了
源碼如下:

 private MBeanAnalyzer(Class<?> mbeanType,
        MBeanIntrospector<M> introspector)
        throws NotCompliantMBeanException {
    if (!mbeanType.isInterface()) {
        throw new NotCompliantMBeanException("Not an interface: " +
                mbeanType.getName());
    } else if (!Modifier.isPublic(mbeanType.getModifiers()) &&
               !Introspector.ALLOW_NONPUBLIC_MBEAN) {
        throw new NotCompliantMBeanException("Interface is not public: " +
            mbeanType.getName());
    }

    try {
        initMaps(mbeanType, introspector);
    } catch (Exception x) {
        throw Introspector.throwException(mbeanType,x);
    }
}
           

好吧!那就自己重寫傳回的對象,即可!

編寫MXBean的方式和MBean的方式是一樣的,隻是将MBean接口改為MXBean接口即可。

總結:Jmx是很強大的一種jvm監控工具,我們在開發中還是必須要掌握的一種技能!