使用JMX監(jiān)控Zookeeper狀態(tài)Java API
一、背景
上一篇通過Java自帶的JConsole來獲取zookeeper狀態(tài)。主要有幾個不方便的地方,zk集群一般會部署3或者5臺,在多個JConsole窗口中切換比較麻煩,各個zk服務(wù)及歷史數(shù)據(jù)之間,不能直觀比較。一般會做一個WEB管理頁面來展示集群狀態(tài),設(shè)置報警閥值來做報警。
二、JVM平臺提供Mbeans
在Java5.0以上版本,有一組API可以讓Java應(yīng)用程序和允許的工具監(jiān)視和管理Java虛擬機(JVM)和虛擬機所在的本機操作系統(tǒng)。該組API在 java.lang.management包??梢酝ㄟ^這些API可以監(jiān)控local端JVM,同時也可以監(jiān)控遠(yuǎn)端JVM。
通過靜態(tài)工廠方法獲取MXBean實例,從本地訪問正在運行的虛擬機的MXBean接口。這些Bean我們從ManagementFactory類中定義的靜態(tài)方法獲??;如ManagementFactory.getOperatingSystemMXBean();其中不足就是只能獲取本地的JVM狀態(tài)。無法獲取遠(yuǎn)程的虛擬機數(shù)據(jù)。
- ClassLoadingMXBean Java虛擬機的類加載系統(tǒng)
- CompilationMXBean Java虛擬機的編譯系統(tǒng)
- MemoryMXBean Java虛擬機的內(nèi)存系統(tǒng)
- RuntimeMXBean Java虛擬機的運行時系統(tǒng)
- OperatingSystemMXBean Java虛擬機在其上運行的操作系統(tǒng)
- GarbageCollectorMXBean Java虛擬機中的垃圾回收器
- MemoryManagerMXBean Java虛擬機中的內(nèi)存管理器
- MemoryPoolMXBean Java虛擬機中的內(nèi)存池
三、Zookeeper提供出來的Mbeans
構(gòu)造MXBean代理實例,通過代理將方法調(diào)用轉(zhuǎn)發(fā)到給定的MBeanServe。JConsole能夠監(jiān)控的項目,通過API都能獲取到。
具體代碼如下:
import java.io.IOException;
import java.lang.management.ClassLoadingMXBean;
import java.lang.management.CompilationMXBean;
import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.lang.management.ThreadMXBean;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.management.InstanceNotFoundException;
import javax.management.IntrospectionException;
import javax.management.JMX;
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import org.apache.zookeeper.server.ConnectionMXBean;
import org.apache.zookeeper.server.DataTreeMXBean;
import org.apache.zookeeper.server.ZooKeeperServerMXBean;
public class ZkJMXTest {
static JMXConnector connector;
/**
* @param args
* @throws IOException
* @throws MalformedObjectNameException
* @throws InstanceNotFoundException
* @throws ReflectionException
* @throws IntrospectionException
*/
public static void main(String[] args) throws IOException, MalformedObjectNameException,
InstanceNotFoundException, IntrospectionException, ReflectionException {
OperatingSystemMXBean osbean = ManagementFactory.getOperatingSystemMXBean();
System.out.println("體系結(jié)構(gòu):" + osbean.getArch());//操作系統(tǒng)體系結(jié)構(gòu)
System.out.println("處理器核數(shù):" + osbean.getAvailableProcessors());///核數(shù)
System.out.println("名字:" + osbean.getName());//名字
System.out.println(osbean.getVersion());//操作系統(tǒng)版本
ThreadMXBean threadBean=ManagementFactory.getThreadMXBean();
System.out.println("活動線程:" + threadBean.getThreadCount());//總線程數(shù)
ClassLoadingMXBean classLoadingMXBean = ManagementFactory.getClassLoadingMXBean();
CompilationMXBean compilationMXBean = ManagementFactory.getCompilationMXBean();
System.out.println("===========");
// 通過 MBeanServer間接地訪問 MXBean 接口
MBeanServerConnection mbsc = createMBeanServer("192.168.1.100", "9991", "controlRole", "123456");
// 操作系統(tǒng)
ObjectName os = new ObjectName("java.lang:type=OperatingSystem");
System.out.println("體系結(jié)構(gòu):" + getAttribute(mbsc, os, "Arch"));//體系結(jié)構(gòu)
System.out.println("處理器核數(shù):" + getAttribute(mbsc, os, "AvailableProcessors"));//核數(shù)
System.out.println("總物理內(nèi)存:" + getAttribute(mbsc, os, "TotalPhysicalMemorySize"));//總物理內(nèi)存
System.out.println("空閑物理內(nèi)存:" + getAttribute(mbsc, os, "FreePhysicalMemorySize"));//空閑物理內(nèi)存
System.out.println("總交換空間:" + getAttribute(mbsc, os, "TotalSwapSpaceSize"));//總交換空間
System.out.println("空閑交換空間:" + getAttribute(mbsc, os, "FreeSwapSpaceSize"));//空閑交換空間
System.out.println("操作系統(tǒng):" + getAttribute(mbsc, os, "Name")+ getAttribute(mbsc, os, "Version"));//操作系統(tǒng)
System.out.println("提交的虛擬內(nèi)存:" + getAttribute(mbsc, os, "CommittedVirtualMemorySize"));//提交的虛擬內(nèi)存
System.out.println("系統(tǒng)cpu使用率:" + getAttribute(mbsc, os, "SystemCpuLoad"));//系統(tǒng)cpu使用率
System.out.println("進(jìn)程cpu使用率:" + getAttribute(mbsc, os, "ProcessCpuLoad"));//進(jìn)程cpu使用率
System.out.println("============");//
// 線程
ObjectName Threading = new ObjectName("java.lang:type=Threading");
System.out.println("活動線程:" + getAttribute(mbsc, Threading, "ThreadCount"));// 活動線程
System.out.println("守護(hù)程序線程:" + getAttribute(mbsc, Threading, "DaemonThreadCount"));// 守護(hù)程序線程
System.out.println("峰值:" + getAttribute(mbsc, Threading, "PeakThreadCount"));// 峰值
System.out.println("啟動的線程總數(shù):" + getAttribute(mbsc, Threading, "TotalStartedThreadCount"));// 啟動的線程總數(shù)
ThreadMXBean threadBean2 = ManagementFactory.newPlatformMXBeanProxy
(mbsc, ManagementFactory.THREAD_MXBEAN_NAME, ThreadMXBean.class);
System.out.println("活動線程:" + threadBean2.getThreadCount());// 活動線程
ThreadMXBean threadBean3 = ManagementFactory.getThreadMXBean();
System.out.println("本地活動線程:" + threadBean3.getThreadCount());// 本地活動線程
System.out.println("============");//
ObjectName Compilation = new ObjectName("java.lang:type=Compilation");
System.out.println("總編譯時間 毫秒:" + getAttribute(mbsc, Compilation, "TotalCompilationTime"));// 總編譯時間 毫秒
System.out.println("============");//
ObjectName ClassLoading = new ObjectName("java.lang:type=ClassLoading");
System.out.println("已加載類總數(shù):" + getAttribute(mbsc, ClassLoading, "TotalLoadedClassCount"));// 已加載類總數(shù)
System.out.println("已加裝當(dāng)前類:" + getAttribute(mbsc, ClassLoading, "LoadedClassCount"));// 已加裝當(dāng)前類
System.out.println("已卸載類總數(shù):" + getAttribute(mbsc, ClassLoading, "UnloadedClassCount"));// 已卸載類總數(shù)
System.out.println("==========================================================");//
// http://zookeeper.apache.org/doc/r3.4.6/zookeeperJMX.html
// org.apache.ZooKeeperService:name0=ReplicatedServer_id1,name1=replica.1,name2=Follower
ObjectName replica = new ObjectName("org.apache.ZooKeeperService:name0=ReplicatedServer_id1,name1=replica.1");
System.out.println("replica.1運行狀態(tài):" + getAttribute(mbsc, replica, "State"));// 運行狀態(tài)
mbsc = createMBeanServer("192.168.1.100", "9992", "controlRole", "123456");
System.out.println("==============節(jié)點樹對象===========");
ObjectName dataTreePattern = new ObjectName("org.apache.ZooKeeperService:name0=ReplicatedServer_id?,name1=replica.?,name2=*,name3=InMemoryDataTree");
Set<ObjectName> dataTreeSets = mbsc.queryNames(dataTreePattern, null);
Iterator<ObjectName> dataTreeIterator = dataTreeSets.iterator();
// 只有一個
while (dataTreeIterator.hasNext()) {
ObjectName dataTreeObjectName = dataTreeIterator.next();
DataTreeMXBean dataTree = JMX.newMBeanProxy(mbsc, dataTreeObjectName, DataTreeMXBean.class);
System.out.println("節(jié)點總數(shù):" + dataTree.getNodeCount());// 節(jié)點總數(shù)
System.out.println("Watch總數(shù):" + dataTree.getWatchCount());// Watch總數(shù)
System.out.println("臨時節(jié)點總數(shù):" + dataTree.countEphemerals());// Watch總數(shù)
System.out.println("節(jié)點名及字符總數(shù):" + dataTree.approximateDataSize());// 節(jié)點全路徑和值的總字符數(shù)
Map<String, String> dataTreeMap = dataTreeObjectName.getKeyPropertyList();
String replicaId = dataTreeMap.get("name1").replace("replica.", "");
String role = dataTreeMap.get("name2");// Follower,Leader,Observer,Standalone
String canonicalName = dataTreeObjectName.getCanonicalName();
int roleEndIndex = canonicalName.indexOf(",name3");
ObjectName roleObjectName = new ObjectName(canonicalName.substring(0, roleEndIndex));
System.out.println("==============zk服務(wù)狀態(tài)===========");
ZooKeeperServerMXBean ZooKeeperServer = JMX.newMBeanProxy(mbsc, roleObjectName, ZooKeeperServerMXBean.class);
System.out.println(role + " 的IP和端口:" + ZooKeeperServer.getClientPort());// IP和端口
System.out.println(role + " 活著的連接數(shù):" + ZooKeeperServer.getNumAliveConnections());// 連接數(shù)
System.out.println(role + " 未完成請求數(shù):" + ZooKeeperServer.getOutstandingRequests());// 未完成的請求數(shù)
System.out.println(role + " 接收的包:" + ZooKeeperServer.getPacketsReceived());// 收到的包
System.out.println(role + " 發(fā)送的包:" + ZooKeeperServer.getPacketsSent());// 發(fā)送的包
System.out.println(role + " 平均延遲(毫秒):" + ZooKeeperServer.getAvgRequestLatency());
System.out.println(role + " 最大延遲(毫秒):" + ZooKeeperServer.getMaxRequestLatency());
System.out.println(role + " 每個客戶端IP允許的最大連接數(shù):" + ZooKeeperServer.getMaxClientCnxnsPerHost());
System.out.println(role + " 最大Session超時(毫秒):" + ZooKeeperServer.getMaxSessionTimeout());
System.out.println(role + " 心跳時間(毫秒):" + ZooKeeperServer.getTickTime());
System.out.println(role + " 版本:" + ZooKeeperServer.getVersion());// 版本
// 三個重置操作
// ZooKeeperServer.resetLatency(); //重置min/avg/max latency statistics
// ZooKeeperServer.resetMaxLatency(); //重置最大延遲統(tǒng)計
// ZooKeeperServer.resetStatistics(); // 重置包和延遲所有統(tǒng)計
System.out.println("==============所有客戶端的連接信息===========");
ObjectName connectionPattern = new ObjectName("org.apache.ZooKeeperService:name0=ReplicatedServer_id?,name1=replica.?,name2=*,name3=Connections,*");
Set<ObjectName> connectionSets = mbsc.queryNames(connectionPattern, null);
List<ObjectName> connectionList = new ArrayList<ObjectName>(connectionSets.size());
connectionList.addAll(connectionSets);
Collections.sort(connectionList);
for (ObjectName connectionON : connectionList) {
System.out.println("=========================");
ConnectionMXBean connectionBean = JMX.newMBeanProxy(mbsc, connectionON, ConnectionMXBean.class);
System.out.println(" IP+Port:" + connectionBean.getSourceIP());//
System.out.println(" SessionId:" + connectionBean.getSessionId());//
System.out.println(" PacketsReceived:" + connectionBean.getPacketsReceived());// 收到的包
System.out.println(" PacketsSent:" + connectionBean.getPacketsSent());// 發(fā)送的包
System.out.println(" MinLatency:" + connectionBean.getMinLatency());//
System.out.println(" AvgLatency:" + connectionBean.getAvgLatency());//
System.out.println(" MaxLatency:" + connectionBean.getMaxLatency());//
System.out.println(" StartedTime:" + connectionBean.getStartedTime());//
System.out.println(" EphemeralNodes:" + connectionBean.getEphemeralNodes().length);//
System.out.println(" EphemeralNodes:" + Arrays.asList(connectionBean.getEphemeralNodes()));//
System.out.println(" OutstandingRequests:" + connectionBean.getOutstandingRequests());//
//connectionBean.resetCounters();
//connectionBean.terminateConnection();
//connectionBean.terminateSession();
}
}
// close connection
if (connector != null) {
connector.close();
}
}
/**
* 建立連接
* @param ip
* @param jmxport
* @return
*/
public static MBeanServerConnection createMBeanServer(String ip,
String jmxport, String userName, String password) {
try {
String jmxURL = "service:jmx:rmi:///jndi/rmi://" + ip + ":"
+ jmxport + "/jmxrmi";
// jmxurl
JMXServiceURL serviceURL = new JMXServiceURL(jmxURL);
Map<String, String[]> map = new HashMap<String, String[]>();
String[] credentials = new String[] { userName, password };
map.put("jmx.remote.credentials", credentials);
connector = JMXConnectorFactory.connect(serviceURL, map);
MBeanServerConnection mbsc = connector.getMBeanServerConnection();
return mbsc;
} catch (IOException ioe) {
ioe.printStackTrace();
System.err.println(ip + ":" + jmxport + " 連接建立失敗");
}
return null;
}
/**
* 使用MBeanServer獲取對象名為[objName]的MBean的[objAttr]屬性值
* <p>
* 靜態(tài)代碼: return MBeanServer.getAttribute(ObjectName name, String attribute)
* @param mbeanServer
* - MBeanServer實例
* @param objName
* - MBean的對象名
* @param objAttr
* - MBean的某個屬性名
* @return 屬性值
*/
private static String getAttribute(MBeanServerConnection mbeanServer,
ObjectName objName, String objAttr) {
if (mbeanServer == null || objName == null || objAttr == null)
throw new IllegalArgumentException();
try {
return String.valueOf(mbeanServer.getAttribute(objName, objAttr));
} catch (Exception e) {
return null;
}
}
}
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,謝謝大家對腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請查看下面相關(guān)鏈接
相關(guān)文章
獲取JPEGImageEncoder和JPEGCode這兩個類的方法
下面小編就為大家?guī)硪黄@取JPEGImageEncoder和JPEGCode這兩個類的方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-07-07
Java數(shù)據(jù)結(jié)構(gòu)之簡單的連接點(link)實現(xiàn)方法示例
這篇文章主要介紹了Java數(shù)據(jù)結(jié)構(gòu)之簡單的連接點(link)實現(xiàn)方法,涉及java指針指向節(jié)點的相關(guān)使用技巧,需要的朋友可以參考下2017-10-10
RestTemplat中關(guān)于getForobject方法的使用
這篇文章主要介紹了RestTemplat中關(guān)于getForobject方法的使用方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07
Spring Boot整合MybatisPlus逆向工程(MySQL/PostgreSQL)
MyBatis-Plus是MyBatis的增強工具,本文主要介紹了Spring Boot整合MybatisPlus逆向工程(MySQL/PostgreSQL),具有一定的參考價值,感興趣的可以了解一下2021-07-07
java讀取resources文件詳解及實現(xiàn)代碼
這篇文章主要介紹了java讀取resources文件詳解及實現(xiàn)代碼的相關(guān)資料,在開發(fā)項目的時候經(jīng)常會遇到讀取文件夾里面的內(nèi)容,需要的朋友可以參考下2017-07-07

