一、zookeeper監控方式
根據官網介紹主要有兩種監控方式,
1:使用ssh建立遠程連接,然后使用"echo stat | nc ip port"命令返回結果。開源項目代表taokeeper。
2:使用JMX監控,文檔[http://zookeeper.apache.org/doc/r3.4.6/zookeeperJMX.html]
我們考慮使用JMX監控是因為運維不希望在服務器之間配置ssh連接,或者openSSH,服務器太多難以管理用戶密碼和公鑰,容易混亂。
二、zookeeper服務開啟JMX監控
修改zookeeper的啟動腳本vim zkServer.sh。找到啟動參數ZOOMAIN,修改為下面值。
其中local.only=false,設為false才能在遠程建立連接。
- ZOOMAIN="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.local.only=false
- -Djava.rmi.server.hostname=127.0.0.1
- -Dcom.sun.management.jmxremote.port=9991
- -Dcom.sun.management.jmxremote.ssl=true
- -Dcom.sun.management.jmxremote.authenticate=true
- -Dcom.sun.management.jmxremote.access.file=/data/zookeeper/conf/jmxremote.access
- -Dcom.sun.management.jmxremote.password.file=/data/zookeeper/conf/jmxremote.password
- -Dzookeeper.jmx.log4j.disable=true
- org.apache.zookeeper.server.quorum.QuorumPeerMain"
在/data/zookeeper/conf目錄下建立2個訪問授權文件, 修改文件權限chmod 600 jmxremote.*
- -rw------- 1 deploy deploy 149 Aug 6 13:44 jmxremote.access
- -rw------- 1 deploy deploy 40 Aug 6 13:46 jmxremote.password
- [deploy@liutp conf]$ pwd
- /data/zookeeper/conf
- [deploy@liutp conf]$ cat jmxremote.access
- monitorRole readonly
- controlRole readwrite \
- create javax.management.monitor.*,javax.management.timer.* \
- unregister
- [deploy@liutp conf]$ cat jmxremote.password
- monitorRole 1234567
- controlRole 1234567
- [deploy@liutp conf]$
關於權限文件內容的設置可以參考jdk里的文件:C:\Java\jdk1.7.0_79\jre\lib\management\jmxremote.password.template
重啟zk服務 :zkServer.sh restart /data/zookeeper/conf/zk1.cfg
三、使用Java自帶的JConsole
在命令行輸入JConsole,再回車。
在彈出的界面選擇“遠程進程”,輸入“服務器IP:9991”(zookeeper服務器的IP和端口)
用戶名:controlRole密碼:1234567就能查看節點數,連接數,watch數
一、背景
上一篇通過Java自帶的JConsole來獲取zookeeper狀態。主要有幾個不方便的地方,zk集群一般會部署3或者5台,在多個JConsole窗口中切換比較麻煩,各個zk服務及歷史數據之間,不能直觀比較。一般會做一個WEB管理頁面來展示集群狀態,設置報警閥值來做報警。
二、JVM平台提供Mbeans
在Java5.0以上版本,有一組API可以讓Java應用程序和允許的工具監視和管理Java虛擬機(JVM)和虛擬機所在的本機操作系統。該組API在 java.lang.management包。可以通過這些API可以監控local端JVM,同時也可以監控遠端JVM。
通過靜態工廠方法獲取MXBean實例,從本地訪問正在運行的虛擬機的MXBean接口。這些Bean我們從ManagementFactory類中定義的靜態方法獲取;如ManagementFactory.getOperatingSystemMXBean();其中不足就是只能獲取本地的JVM狀態。無法獲取遠程的虛擬機數據。
- ClassLoadingMXBean Java虛擬機的類加載系統
- CompilationMXBean Java虛擬機的編譯系統
- MemoryMXBean Java虛擬機的內存系統
- RuntimeMXBean Java虛擬機的運行時系統
- OperatingSystemMXBean Java虛擬機在其上運行的操作系統
- GarbageCollectorMXBean Java虛擬機中的垃圾回收器
- MemoryManagerMXBean Java虛擬機中的內存管理器
- MemoryPoolMXBean Java虛擬機中的內存池
三、Zookeeper提供出來的Mbeans
構造MXBean代理實例,通過代理將方法調用轉發到給定的MBeanServe。JConsole能夠監控的項目,通過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("體系結構:" + osbean.getArch());//操作系統體系結構
- System.out.println("處理器核數:" + osbean.getAvailableProcessors());///核數
- System.out.println("名字:" + osbean.getName());//名字
- System.out.println(osbean.getVersion());//操作系統版本
- ThreadMXBean threadBean=ManagementFactory.getThreadMXBean();
- System.out.println("活動線程:" + threadBean.getThreadCount());//總線程數
- ClassLoadingMXBean classLoadingMXBean = ManagementFactory.getClassLoadingMXBean();
- CompilationMXBean compilationMXBean = ManagementFactory.getCompilationMXBean();
- System.out.println("===========");
- // 通過 MBeanServer間接地訪問 MXBean 接口
- MBeanServerConnection mbsc = createMBeanServer("192.168.1.100", "9991", "controlRole", "123456");
- // 操作系統
- ObjectName os = new ObjectName("java.lang:type=OperatingSystem");
- System.out.println("體系結構:" + getAttribute(mbsc, os, "Arch"));//體系結構
- System.out.println("處理器核數:" + getAttribute(mbsc, os, "AvailableProcessors"));//核數
- System.out.println("總物理內存:" + getAttribute(mbsc, os, "TotalPhysicalMemorySize"));//總物理內存
- System.out.println("空閑物理內存:" + getAttribute(mbsc, os, "FreePhysicalMemorySize"));//空閑物理內存
- System.out.println("總交換空間:" + getAttribute(mbsc, os, "TotalSwapSpaceSize"));//總交換空間
- System.out.println("空閑交換空間:" + getAttribute(mbsc, os, "FreeSwapSpaceSize"));//空閑交換空間
- System.out.println("操作系統:" + getAttribute(mbsc, os, "Name")+ getAttribute(mbsc, os, "Version"));//操作系統
- System.out.println("提交的虛擬內存:" + getAttribute(mbsc, os, "CommittedVirtualMemorySize"));//提交的虛擬內存
- System.out.println("系統cpu使用率:" + getAttribute(mbsc, os, "SystemCpuLoad"));//系統cpu使用率
- System.out.println("進程cpu使用率:" + getAttribute(mbsc, os, "ProcessCpuLoad"));//進程cpu使用率
- System.out.println("============");//
- // 線程
- ObjectName Threading = new ObjectName("java.lang:type=Threading");
- System.out.println("活動線程:" + getAttribute(mbsc, Threading, "ThreadCount"));// 活動線程
- System.out.println("守護程序線程:" + getAttribute(mbsc, Threading, "DaemonThreadCount"));// 守護程序線程
- System.out.println("峰值:" + getAttribute(mbsc, Threading, "PeakThreadCount"));// 峰值
- System.out.println("啟動的線程總數:" + getAttribute(mbsc, Threading, "TotalStartedThreadCount"));// 啟動的線程總數
- 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("已加載類總數:" + getAttribute(mbsc, ClassLoading, "TotalLoadedClassCount"));// 已加載類總數
- System.out.println("已加裝當前類:" + getAttribute(mbsc, ClassLoading, "LoadedClassCount"));// 已加裝當前類
- System.out.println("已卸載類總數:" + getAttribute(mbsc, ClassLoading, "UnloadedClassCount"));// 已卸載類總數
- 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運行狀態:" + getAttribute(mbsc, replica, "State"));// 運行狀態
- mbsc = createMBeanServer("192.168.1.100", "9992", "controlRole", "123456");
- System.out.println("==============節點樹對象===========");
- 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("節點總數:" + dataTree.getNodeCount());// 節點總數
- System.out.println("Watch總數:" + dataTree.getWatchCount());// Watch總數
- System.out.println("臨時節點總數:" + dataTree.countEphemerals());// Watch總數
- System.out.println("節點名及字符總數:" + dataTree.approximateDataSize());// 節點全路徑和值的總字符數
- 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服務狀態===========");
- ZooKeeperServerMXBean ZooKeeperServer = JMX.newMBeanProxy(mbsc, roleObjectName, ZooKeeperServerMXBean.class);
- System.out.println(role + " 的IP和端口:" + ZooKeeperServer.getClientPort());// IP和端口
- System.out.println(role + " 活着的連接數:" + ZooKeeperServer.getNumAliveConnections());// 連接數
- System.out.println(role + " 未完成請求數:" + ZooKeeperServer.getOutstandingRequests());// 未完成的請求數
- System.out.println(role + " 接收的包:" + ZooKeeperServer.getPacketsReceived());// 收到的包
- System.out.println(role + " 發送的包:" + ZooKeeperServer.getPacketsSent());// 發送的包
- System.out.println(role + " 平均延遲(毫秒):" + ZooKeeperServer.getAvgRequestLatency());
- System.out.println(role + " 最大延遲(毫秒):" + ZooKeeperServer.getMaxRequestLatency());
- System.out.println(role + " 每個客戶端IP允許的最大連接數:" + 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(); //重置最大延遲統計
- // ZooKeeperServer.resetStatistics(); // 重置包和延遲所有統計
- 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());// 發送的包
- 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>
- * 靜態代碼: 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;
- }
- }
- }