• Tomcat扩展——监控



    (转过来,源地址: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


    相关的内容:

    Tomcat源代码走读1:从何開始

    Tomcat源代码走读2:启动过程

    Tomcat源代码走读5:请求处理

    Tomcat源代码走读——内存泄露检測






  • 相关阅读:
    拒绝喝酒理由1
    动态调用事件,事件的方法
    c#发送图片
    c#截屏功能的实现
    devexpress中文讨论论坛
    解析javascript变量
    devexpress_PivotGrid说明
    python学习之老男孩python全栈第九期_day022知识点总结——初识面向对象
    python学习之老男孩python全栈第九期_day022作业
    员工信息表
  • 原文地址:https://www.cnblogs.com/cxchanpin/p/6923544.html
Copyright © 2020-2023  润新知