(转过来,源地址:http://www.jmatrix.org/notes/1067.html)
近期心血来潮。想能否够通过添加一个tomcat的扩展,来持续收集tomcatserver本身的性能信息。如线程池的各项数据,请求数等等,这样能够配合业务方面的监控,能够更方便的分析调整tomcat配置,以提供更好的服务。
这样也不须要每次通过连接jmx去观察数据,并且idc环境要开启jmx。还得涉及各种安全问题…….
Tomcat manager中StatusManagerServlet就是通过JMX提供了Tomcat服务的当前状态信息。我也会“抄袭”这里的代码来收集server数据。
要想定时的收集Tomcat的数据,须要在tomcat启动过程中,启一个定时任务去不停的收集服务信息,之后依据自己的须要,看是通过写日志方式保存。还是上报,抑或其他方式。
要做到不侵入tomcat本身源代码。能够选择通过Listener的方式,实现一个自己定义Listener,监听服务启动事件,启动数据採集任务。定时收集数据,如:
public class ServerInfoMonitorLifecycleListener implementsLifecycleListener { private ServerInfoCollection collect = new ServerInfoCollection(); @Override public void lifecycleEvent(LifecycleEvent event ) { Lifecycle lifecycle = event .getLifecycle(); if (Lifecycle.AFTER_START_EVENT .equals(event .getType()) && lifecycle instanceof Server) { collect.startMonitor(); } if (Lifecycle.BEFORE_STOP_EVENT .equals(event .getType()) && lifecycle instanceof Server) { collect.stopMonitor(); } } }
这里监控的是Server的启动事件,须要注意。假设你想监控其他container,如host。context等。则配置listener的时候须要放到相应的container。大多数情况下。我们还是习惯配置在Server这一级别,确实在Server这一级别是最方便的。
Tomcat本身的个别listener。想监听host,context等的事件是通过监听到Server事件的时候依次对server以下的host,context等加入listener。
有了定时收集tomcat数据的定时任务,以下就是数据的收集了。
首先得先获取须要的Mbean。如:
// Retrieve the MBean server mBeanServer = Registry.getRegistry( null , null ).getMBeanServer(); try { // Query Thread Pools threadPools .clear(); String onStr = "*:type=ThreadPool,*" ; ObjectName objectName = new ObjectName(onStr ); Set set = mBeanServer .queryMBeans( objectName, null ); Iterator iterator = set .iterator(); while (iterator .hasNext()) { ObjectInstance oi = iterator.next(); threadPools .addElement(oi .getObjectName()); } // Query Global Request Processors globalRequestProcessors .clear(); 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()); } } catch (Exception e ) { log.error( "init failed." , e ); }
通过Mbean获取tomcat性能数据:
Enumeration enumeration = threadPools .elements(); while (enumeration .hasMoreElements()) { ObjectName objectName = enumeration .nextElement(); String name = objectName .getKeyProperty("name" ); ServerInfo serverInfo = new ServerInfo(); serverInfo .setMaxThreads((Integer) mBeanServer .getAttribute( objectName , "maxThreads" )); serverInfo .setCurrentThreadCount((Integer) mBeanServer .getAttribute( objectName ,"currentThreadCount" )); serverInfo .setCurrentThreadsBusy((Integer) mBeanServer .getAttribute( objectName ,"currentThreadsBusy" )); try { Object value = mBeanServer .getAttribute(objectName , "keepAliveCount" ); serverInfo .setKeepAliveCount((Integer) value ); } catch (Exception e ) { // Ignore } ObjectName grpName = null ; Enumeration reqEnumer =globalRequestProcessors .elements(); while (reqEnumer .hasMoreElements()) { ObjectName reqObjName = reqEnumer .nextElement(); if (name .equals(reqObjName .getKeyProperty( "name"))) { grpName = reqObjName ; } } if (grpName == null) { return ; } serverInfo .setMaxTime((Long) mBeanServer .getAttribute(grpName , "maxTime" )); serverInfo .setProcessingTime((Long) mBeanServer .getAttribute( grpName, "processingTime" )); serverInfo .setRequestCount((Integer) mBeanServer .getAttribute( grpName, "requestCount" )); serverInfo .setErrorCount((Integer) mBeanServer .getAttribute( grpName, "errorCount" )); serverInfo .setBytesReceived((Long) mBeanServer .getAttribute( grpName, "bytesReceived" )); serverInfo .setBytesSent((Long) mBeanServer .getAttribute( grpName, "bytesSent" )); store.storeInfo( serverInfo ); }
在server.xml配置好自己定义的listener,启动tomcat,便能够看到收集到的数据。如(这里为了測试。收集到的数据直接写日志):
ServerInfo:maxThreads:200,currentThreadCount:16,busyThreadCount:6,keepAliveCount:0,maxTime:6166,requestCount:57,errorCount:0,processTime:10380,bytesRec:0,bytesSend:238874
当然。还有非常多其他的信息能够收集。看详细须要。
另外。还能够借助Value链条,编写自己的Value来上报请求处理时间,异常情况等等。
基础的代码可在github上看看:https://github.com/jjmatrix/tomcat-extension
相关的内容: