Tomcat學習--tomcat執行狀態監控
阿新 • • 發佈:2019-02-09
上一篇部落格Tomcat學習--war服務相關狀態資訊監控中我們已經瞭解了一下對war包的啟動、停止、執行狀態、過載和解除安裝操作的實現機制,接下來我們用這篇部落格瞭解一下tomcat執行過程中伺服器,作業系統,jvm和war的一些狀態資訊。
目前tomcat將執行的過程中的一些狀態資訊通過JMX的MBeanServer機制儲存起來,所以目前的實現就是通過MBeanServer來獲取資料就好,可以參考tomcat的StatusManagerServlet的實現邏輯。
本篇部落格只是簡單的獲取了一些資料進行展示
1、web.xml中配置如下
<!-- 檢視tomcat中自身及每個war服務的執行情況 --> <servlet> <servlet-name>tomcat-monitor-info</servlet-name> <servlet-class>com.tianjunwei.tomcat.servlet.MonitorInfoServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>tomcat-monitor-info</servlet-name> <url-pattern>/tomcat_monitor_info</url-pattern> </servlet-mapping>
2、實現原始碼如下:
public class MonitorInfoServlet extends HttpServlet implements NotificationListener { private static final long serialVersionUID = 1L; protected static MBeanServer mBeanServer = null; protected final Vector<ObjectName> protocolHandlers = new Vector<>(); protected final Vector<ObjectName> threadPools = new Vector<>(); protected final Vector<ObjectName> globalRequestProcessors = new Vector<>(); protected final Vector<ObjectName> requestProcessors = new Vector<>(); @Override public void init() throws ServletException { // Retrieve the MBean server mBeanServer = Registry.getRegistry(null, null).getMBeanServer(); try { // Query protocol handlers String onStr = "*:type=ProtocolHandler,*"; ObjectName objectName = new ObjectName(onStr); Set<ObjectInstance> set = mBeanServer.queryMBeans(objectName, null); Iterator<ObjectInstance> iterator = set.iterator(); while (iterator.hasNext()) { ObjectInstance oi = iterator.next(); protocolHandlers.addElement(oi.getObjectName()); } // Query Thread Pools onStr = "*:type=ThreadPool,*"; objectName = new ObjectName(onStr); set = mBeanServer.queryMBeans(objectName, null); iterator = set.iterator(); while (iterator.hasNext()) { ObjectInstance oi = iterator.next(); threadPools.addElement(oi.getObjectName()); } // Query Global Request Processors onStr = "*:type=GlobalRequestProcessor,*"; objectName = new ObjectName(onStr); set = mBeanServer.queryMBeans(objectName, null); iterator = set.iterator(); while (iterator.hasNext()) { ObjectInstance oi = iterator.next(); globalRequestProcessors.addElement(oi.getObjectName()); } // Query Request Processors onStr = "*:type=RequestProcessor,*"; objectName = new ObjectName(onStr); set = mBeanServer.queryMBeans(objectName, null); iterator = set.iterator(); while (iterator.hasNext()) { ObjectInstance oi = iterator.next(); requestProcessors.addElement(oi.getObjectName()); } // Register with MBean server onStr = "JMImplementation:type=MBeanServerDelegate"; objectName = new ObjectName(onStr); mBeanServer.addNotificationListener(objectName, this, null, null); } catch (Exception e) { e.printStackTrace(); } } public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException{ PrintWriter writer = response.getWriter(); Map<String, Object> dataMap = new HashMap<String,Object>(); dataMap.put("server", getServerData()); dataMap.put("os", getOsData()); dataMap.put("jvm", getJVMData()); dataMap.put("war", getWarData()); writer.write(JSON.toJSONString(dataMap)); writer.flush(); } /** * 獲取作業系統及jvm相關的資訊 */ public static Map<String, Object> getServerData(){ Map<String, Object> serverMap =new HashMap<String, Object>(); serverMap.put("tomcat_version", ServerInfo.getServerInfo()); serverMap.put("jvm_version", System.getProperty("java.runtime.version")); serverMap.put("jvm_vendor", System.getProperty("java.vm.vendor")); serverMap.put("os_name", System.getProperty("os.name")); serverMap.put("os_version", System.getProperty("os.version")); serverMap.put("os_arch", System.getProperty("os.arch")); try { InetAddress address = InetAddress.getLocalHost(); serverMap.put("hostName", address.getHostName()); serverMap.put("hostAddress", address.getHostAddress()); } catch (UnknownHostException e) { serverMap.put("hostName", "-"); serverMap.put("hostAddress", "-"); } return serverMap; } /** * * 獲取作業系統相關資訊 */ public static Map<String, Object> getOsData(){ Map<String, Object> osMap = new HashMap<String, Object>(); long[] result = new long[16]; boolean ok = false; try { String methodName = "info"; Class<?> paramTypes[] = new Class[1]; paramTypes[0] = result.getClass(); Object paramValues[] = new Object[1]; paramValues[0] = result; Method method = Class.forName("org.apache.tomcat.jni.OS") .getMethod(methodName, paramTypes); method.invoke(null, paramValues); ok = true; } catch (Throwable t) { t = ExceptionUtils.unwrapInvocationTargetException(t); ExceptionUtils.handleThrowable(t); } if (ok) { osMap.put(" Physical memory",formatSize(Long.valueOf(result[0]), true)); osMap.put(" Available memory: ",formatSize(Long.valueOf(result[1]), true)); osMap.put(" Total page file: ",formatSize(Long.valueOf(result[2]), true)); osMap.put(" Free page file: ",formatSize(Long.valueOf(result[3]), true)); osMap.put(" Memory load: ",Long.valueOf(result[6])); osMap.put(" Process kernel time: ",formatTime(Long.valueOf(result[11] / 1000), true)); osMap.put(" Process user time: ",formatTime(Long.valueOf(result[12] / 1000), true)); } return osMap; } public static Map<String, Object> getJVMData(){ Map<String, Object> jvmMap = new HashMap<String,Object>(); SortedMap<String, MemoryPoolMXBean> memoryPoolMBeans = new TreeMap<>(); for (MemoryPoolMXBean mbean: ManagementFactory.getMemoryPoolMXBeans()) { String sortKey = mbean.getType() + ":" + mbean.getName(); memoryPoolMBeans.put(sortKey, mbean); } jvmMap.put("free_memory",Runtime.getRuntime().freeMemory()); jvmMap.put("total_memory",Runtime.getRuntime().totalMemory()); jvmMap.put("max_memory" , Runtime.getRuntime().maxMemory()); List<Map<String, Object>> memory_list = new ArrayList<Map<String, Object>>(); jvmMap.put("memory_pool", memory_list); for (MemoryPoolMXBean memoryPoolMBean : memoryPoolMBeans.values()) { MemoryUsage usage = memoryPoolMBean.getUsage(); Map<String, Object> useMap = new HashMap<String, Object>(); useMap.put("name",memoryPoolMBean.getName()); useMap.put("type",memoryPoolMBean.getType()); useMap.put("usageInit",usage.getInit()); useMap.put("usageCommitted",usage.getCommitted()); useMap.put("usageMax",usage.getMax()); useMap.put("usageUsed",usage.getUsed()); memory_list.add(useMap); } return jvmMap; } public static Map<String,Object> getWarData(){ Map<String,Object> dataMap=new HashMap<String, Object>(); try { //堆使用 ObjectName heapObjName = new ObjectName("java.lang:type=Memory"); MemoryUsage heapMemoryUsage = MemoryUsage .from((CompositeDataSupport) mBeanServer.getAttribute(heapObjName, "HeapMemoryUsage")); dataMap.put("memoryUse", heapMemoryUsage.getUsed()); dataMap.put("memoryMax", heapMemoryUsage.getMax()); ObjectName runtimeObjName = new ObjectName("java.lang:type=Runtime"); RuntimeMXBean runtimeMXBean=ManagementFactory.getPlatformMXBean (mBeanServer, RuntimeMXBean.class); dataMap.put("uptime",runtimeMXBean.getUptime()); //永久代使用 ObjectName metaObjName = new ObjectName("java.lang:type=MemoryPool,name=Metaspace"); MemoryUsage metaMemoryUsage = MemoryUsage .from((CompositeDataSupport) mBeanServer.getAttribute(metaObjName, "Usage")); dataMap.put("metaspaceUse", (int)(metaMemoryUsage.getUsed()/(1024*1024))); dataMap.put("metaspaceMax", (int)(metaMemoryUsage.getMax()/(1024*1024))); //執行緒數連線數 ObjectName threadObjName = new ObjectName("Catalina:type=ThreadPool,name=*"); ObjectName threadMXBean=mBeanServer.queryNames(threadObjName, null).iterator().next(); dataMap.put("connectionCount", mBeanServer.getAttribute(threadMXBean, "connectionCount")); dataMap.put("maxConnections", mBeanServer.getAttribute(threadMXBean, "maxConnections")); dataMap.put("currentThreadCount", mBeanServer.getAttribute(threadMXBean, "currentThreadCount")); dataMap.put("maxThreads", mBeanServer.getAttribute(threadMXBean, "maxThreads")); //請求、錯誤請求、傳送接收資料量 ObjectName grpObjName = new ObjectName("Catalina:type=GlobalRequestProcessor,*"); ObjectName requObjName=mBeanServer.queryNames(grpObjName, null).iterator().next(); dataMap.put("requestCount", mBeanServer.getAttribute(requObjName, "requestCount")); dataMap.put("errorCount", mBeanServer.getAttribute(requObjName, "errorCount")); //context Host host = MyHostConfig.myHost; List<Map<String,Object>> contexts=new ArrayList<Map<String,Object>>(); for(Container container:host.findChildren()){ Context context=(Context)container; String name=context.getName().trim(); if("".equals(name)){ continue; } contexts.add(parseContext(context,mBeanServer)); } dataMap.put("contexts", contexts); } catch (Exception e) { e.printStackTrace(); } return dataMap; } private static Map<String,Object> parseContext(Context context,MBeanServer mbsc) throws Exception{ Map<String,Object> contextMap=new HashMap<String,Object>(); ObjectName objectName=context.getObjectName(); contextMap.put("name", context.getName().trim()); contextMap.put("state", context.getStateName()); /* contextMap.put("sessionTimeout", context.getSessionTimeout());*/ contextMap.put("requestCount", mbsc.getAttribute(objectName, "requestCount")); contextMap.put("errorCount", mbsc.getAttribute(objectName, "errorCount")); Manager manager=context.getManager(); Session[] sessions=manager.findSessions(); contextMap.put("sessionCount", sessions.length); List<Map<String,Object>> sessionsInfo=new ArrayList<>(); for(int i=0;i<sessions.length;i++){ Map<String,Object> session=new HashMap<>(); session.put("sessionId", sessions[i].getId()); // session.put("viewIp", sessions[i].getSession().ge); session.put("idleTIme", sessions[i].getIdleTime()); session.put("inactiveIntervalTime", sessions[i].getMaxInactiveInterval()); session.put("lastAcessTime", sessions[i].getLastAccessedTime()); sessionsInfo.add(session); } contextMap.put("sessions", sessionsInfo); return contextMap; } public static Map<String,Object> getData(){ MBeanServer mBeanServer = Registry.getRegistry(null,null).getMBeanServer(); String onStr = "*:type=ThreadPool,*"; Map<String,Object> map = new HashMap<String,Object>(); try{ ObjectName objectName = new ObjectName(onStr); Set set = mBeanServer.queryMBeans(objectName, null); Vector<ObjectName> threadPool = new Vector<ObjectName>(); Iterator iterator = set.iterator(); while(iterator.hasNext()){ ObjectInstance oi = (ObjectInstance) iterator.next(); threadPool.addElement(oi.getObjectName()); } Vector<ObjectName> globalRequestProcessors = new Vector<ObjectName>(); onStr = "*:type=GlobalRequestProcessor,*"; objectName = new ObjectName(onStr); set.clear(); set = mBeanServer.queryMBeans(objectName, null); iterator = set.iterator(); while(iterator.hasNext()){ ObjectInstance oi = (ObjectInstance) iterator.next(); globalRequestProcessors.addElement(oi.getObjectName()); } Enumeration<ObjectName> enumeration = threadPool.elements(); while(enumeration.hasMoreElements()){ ObjectName objectName1 = enumeration.nextElement(); map.put("maxThread", mBeanServer.getAttribute(objectName1, "maxThreads")); map.put("currentThreadCount", mBeanServer.getAttribute(objectName1, "currentThreadCount")); map.put("connectionCount", mBeanServer.getAttribute(objectName1, "connectionCount")); map.put("maxConnections", mBeanServer.getAttribute(objectName1, "maxConnections")); } Enumeration<ObjectName> reqEnume = globalRequestProcessors.elements(); while(reqEnume.hasMoreElements()){ ObjectName reqObjectName = reqEnume.nextElement(); map.put("processingTime", mBeanServer.getAttribute(reqObjectName, "processingTime")); map.put("requestCount", mBeanServer.getAttribute(reqObjectName, "requestCount")); map.put("errorCount", mBeanServer.getAttribute(reqObjectName, "errorCount")); } map.put("maxMemory", formatSize(Long.valueOf(Runtime.getRuntime().maxMemory()), true)); SortedMap<String, MemoryPoolMXBean> memoryPoolMBeans = new TreeMap<String, MemoryPoolMXBean>(); for (MemoryPoolMXBean mbean : ManagementFactory.getMemoryPoolMXBeans()) { String sortKey = mbean.getType() + ":" + mbean.getName(); memoryPoolMBeans.put(sortKey, mbean); } Long usedMemory = 0l; for (MemoryPoolMXBean memoryPoolMBean : memoryPoolMBeans.values()) { MemoryUsage usage = memoryPoolMBean.getUsage(); usedMemory = usedMemory + Long.valueOf(usage.getUsed()); } map.put("usedMemory", formatSize(usedMemory, true)); /*long connectionCount = (Long) mBeanServer.getAttribute(objectNameData, "connectionCount"); int maxConnections = (int) mBeanServer.getAttribute(objectNameData, "maxConnections");*/ }catch(Exception e){ e.printStackTrace(); } return map; } public static long formatSize(Object obj, boolean mb) { long bytes = -1L; if (obj instanceof Long) { bytes = ((Long) obj).longValue(); } else if (obj instanceof Integer) { bytes = ((Integer) obj).intValue(); } if (mb) { StringBuilder buff = new StringBuilder(); if (bytes < 0) { buff.append('-'); bytes = -bytes; } long mbytes = bytes / (1024 * 1024); long rest = ((bytes - (mbytes * (1024 * 1024))) * 100) / (1024 * 1024); buff.append(mbytes).append('.'); if (rest < 10) { buff.append('0'); } buff.append(rest); double d = Double.parseDouble(buff.toString()); Long l = (long) d; return l; } else { return (bytes / 1024); } } public static String formatTime(Object obj) { long time = -1L; if (obj instanceof Long) { time = ((Long) obj).longValue(); } else if (obj instanceof Integer) { time = ((Integer) obj).intValue(); } if (time > 1000 *1000) { return ((((float) time ) / 1000) + " s"); } else if(time > 1000) { return (time + " ms"); }else { return ((((float) time ) / 1000) + " ms"); } } public static String formatTime(Object obj, boolean seconds) { long time = -1L; if (obj instanceof Long) { time = ((Long) obj).longValue(); } else if (obj instanceof Integer) { time = ((Integer) obj).intValue(); } if (seconds) { return ((((float) time ) / 1000) + " s"); } else { return (time + " ms"); } } @Override public void handleNotification(Notification notification, java.lang.Object handback) { if (notification instanceof MBeanServerNotification) { ObjectName objectName = ((MBeanServerNotification) notification).getMBeanName(); if (notification.getType().equals (MBeanServerNotification.REGISTRATION_NOTIFICATION)) { String type = objectName.getKeyProperty("type"); if (type != null) { if (type.equals("ProtocolHandler")) { protocolHandlers.addElement(objectName); } else if (type.equals("ThreadPool")) { threadPools.addElement(objectName); } else if (type.equals("GlobalRequestProcessor")) { globalRequestProcessors.addElement(objectName); } else if (type.equals("RequestProcessor")) { requestProcessors.addElement(objectName); } } } else if (notification.getType().equals (MBeanServerNotification.UNREGISTRATION_NOTIFICATION)) { String type = objectName.getKeyProperty("type"); if (type != null) { if (type.equals("ProtocolHandler")) { protocolHandlers.removeElement(objectName); } else if (type.equals("ThreadPool")) { threadPools.removeElement(objectName); } else if (type.equals("GlobalRequestProcessor")) { globalRequestProcessors.removeElement(objectName); } else if (type.equals("RequestProcessor")) { requestProcessors.removeElement(objectName); } } String j2eeType = objectName.getKeyProperty("j2eeType"); if (j2eeType != null) { } } } } }
3、獲取的結果資料如下:
程式碼地址Github{ "jvm": { "total_memory": 48758784, "memory_pool": [{ "usageMax": 11010048, "name": "PS Eden Space", "usageUsed": 6111136, "type": "HEAP", "usageCommitted": 10485760, "usageInit": 13107200 }, { "usageMax": 35127296, "name": "PS Old Gen", "usageUsed": 19668376, "type": "HEAP", "usageCommitted": 35127296, "usageInit": 35127296 }, { "usageMax": 3145728, "name": "PS Survivor Space", "usageUsed": 1950184, "type": "HEAP", "usageCommitted": 3145728, "usageInit": 2097152 }, { "usageMax": 104857600, "name": "Code Cache", "usageUsed": 11987072, "type": "NON_HEAP", "usageCommitted": 12255232, "usageInit": 2555904 }, { "usageMax": 1073741824, "name": "Compressed Class Space", "usageUsed": 3185400, "type": "NON_HEAP", "usageCommitted": 3538944, "usageInit": 0 }, { "usageMax": -1, "name": "Metaspace", "usageUsed": 31663032, "type": "NON_HEAP", "usageCommitted": 32636928, "usageInit": 0 }], "free_memory": 21029088, "max_memory": 48758784 }, "server": { "hostName": "nb-hz20036325", "tomcat_version": "Apache Tomcat/8.5.24", "jvm_vendor": "Oracle Corporation", "os_version": "6.1", "os_arch": "amd64", "os_name": "Windows 7", "hostAddress": "10.13.80.12", "jvm_version": "1.8.0_151-b12" }, "os": { " Free page file: ": 17006, " Available memory: ": 4869, " Physical memory": 12241, " Process user time: ": "12.324 s", " Total page file: ": 24481, " Process kernel time: ": "7.254 s", " Memory load: ": 60 }, "war": { "requestCount": 112, "connectionCount": 2, "currentThreadCount": 10, "memoryMax": 48758784, "metaspaceUse": 30, "contexts": [{ "requestCount": 0, "sessions": [], "sessionCount": 0, "name": "/examples", "state": "STARTED", "errorCount": 0 }, { "requestCount": 0, "sessions": [], "sessionCount": 0, "name": "/host-manager", "state": "STARTED", "errorCount": 0 }, { "requestCount": 48, "sessions": [{ "inactiveIntervalTime": 1800, "lastAcessTime": 1525247083747, "sessionId": "11C58869BBF32D217EFF3F8B725982E6", "idleTIme": 612935 }], "sessionCount": 1, "name": "/manager", "state": "STARTED", "errorCount": 1 }, { "requestCount": 9, "sessions": [], "sessionCount": 0, "name": "/docs", "state": "STARTED", "errorCount": 0 }, { "requestCount": 2, "sessions": [], "sessionCount": 0, "name": "/war_mointor", "state": "STARTED", "errorCount": 0 }], "maxThreads": 200, "errorCount": 4, "memoryUse": 27729696, "uptime": 11892453, "metaspaceMax": 0, "maxConnections": 10000 } }