文章目錄
- 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代理
* 遠端管理
圖檔如下:
監控層的作用就是使用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監控工具,我們在開發中還是必須要掌握的一種技能!