`
toking79
  • 浏览: 23023 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

Tomcat源码系列8--Tomcat的JMX管理2

阅读更多

前面讲到了JMX的体系,下面从Tomcat源代码启动过程分析MBeans组件注册到MBeanServer的过程 。

(org.apache.catalina.startup.Bootstrap.main(String))

public static void main(String args[]) {
       …
        if (daemon == null) {
            daemon = new Bootstrap();
            try {
                daemon.init();   ★1
            } catch (Throwable t) {
                t.printStackTrace();
                return;
            }
        }
        try {
            String command = "start";
            if (args.length > 0) {
                command = args[args.length - 1];
            }
            if (command.equals("startd")) {
                args[0] = "start";
                daemon.load(args);
                daemon.start();
            } else if (command.equals("stopd")) {
                args[0] = "stop";
                daemon.stop();
            } else if (command.equals("start")) {
                daemon.setAwait(true);
                daemon.load(args);   ★2

             // Catalina的start方法被调用
                daemon.start();        ★3 
            } else if (command.equals("stop")) {
                daemon.stopServer(args);
            }
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }

    
★1

daemon.init()会调用Bootstrap#createClassLoader方法,该方法会将对象名为StandardClassloader的MBean注册并返回Classloader。
(org.apache.catalina.startup.Bootstrap.createClassLoader(String, ClassLoader)) 

private ClassLoader createClassLoader(String name, ClassLoader parent) 
        throws Exception { 
…… 
ClassLoader classLoader = ClassLoaderFactory.createClassLoader 
            (unpacked, packed, urls, parent); 

        // Retrieving MBean server 
        MBeanServer mBeanServer = null; 
        if (MBeanServerFactory.findMBeanServer(null).size() > 0) { 
            mBeanServer = 
                (MBeanServer) MBeanServerFactory.findMBeanServer(null).get(0); 
        } else { 
            mBeanServer = MBeanServerFactory.createMBeanServer(); 
        } 

        //注册Server类加载器MBeans 
        ObjectName objectName = 
            new ObjectName("Catalina:type=ServerClassLoader,name=" + name); 
        mBeanServer.registerMBean(classLoader, objectName); 

        return classLoader; 
}

 
common、server、shared三个classloader会被依序生成,并被注册到mBeanServer中去。这三个Classloader都是StandardClassloader,并且实现了StandardClassloaderMBean接口。因为StandardClassloaderMBean接口没有暴露任何的属性和方法,所以在Jconsole窗口中将看不到StandardClassloader的属性和方法显示。
★2

daemon.load(args)是Catalina载入的过程,standardServer、StandardService、Connector将会被依次初始化并完成Mbean的注册。
1) StandardServer初始化注册。
(org.apache.catalina.core.StandardServer.initialize()) 
  

public void initialize() 
        throws LifecycleException 
    { 
        if (initialized) { 
                log.info(sm.getString("standardServer.initialize.initialized")); 
            return; 
        } 
        initialized = true; 

        if( oname==null ) { 
            try { 
               //注册StandardServer的MBeans 
                oname=new ObjectName( "Catalina:type=Server"); 
                Registry.getRegistry(null, null) 
                    .registerComponent(this, oname, null ); 
            } catch (Exception e) { 
                log.error("Error registering ",e); 
            } 
        } 
        
        // Initialize our defined Services 
        for (int i = 0; i < services.length; i++) { 
            services[i].initialize(); 
        } 
    }

 
2) StandardServer被注册后,它向外暴露了它的属性和await()和storeConfig()两个方法。
StandardService初始化并注册
(org.apache.catalina.core.StandardService.initialize()) 

public void initialize() 
            throws LifecycleException 
    { 
        if (initialized) { 
            log.info(sm.getString("standardService.initialize.initialized")); 
            return; 
        } 
        initialized = true; 

        if( oname==null ) { 
            try { 
                // StandardService的MBeans被注册 
                Container engine=this.getContainer(); 
                domain=engine.getName(); 
                oname=new ObjectName(domain + ":type=Service,serviceName="+name); 
                this.controller=oname; 
                Registry.getRegistry(null, null) 
                    .registerComponent(this, oname, null); 
            } catch (Exception e) { 
                log.error("Error registering ",e); 
            }  } 
            
            
        } 
        if( server==null ) { 
            
            ServerFactory.getServer().addService(this); 
        } 
        //初始化我们定义的连接 
        synchronized (connectors) { 
                for (int i = 0; i < connectors.length; i++) { 
                    connectors[i].initialize(); 
                } 
        }

 
StandardService被注册后,它向外暴露了它的属性和stop()和start()两个方法。在Jconsole中可以对这两个方法进行操作。
3) 对象名为“Catalina:type=Connector port=8080”、“Catalina:type=Connector port=8009”的Connector被注册。
(org.apache.catalina.connector.Connector.initialize()) 
    

public void initialize() 
        throws LifecycleException 
    { 
        if (initialized) { 
            log.info(sm.getString("coyoteConnector.alreadyInitialized")); 
           return; 
        } 
        this.initialized = true; 

        if( oname == null && (container instanceof StandardEngine)) { 
            try { 
                // we are loaded directly, via API - and no name was given to us 
                StandardEngine cb=(StandardEngine)container; 
                String encodedAddr = null; 
                if (getAddress() != null) { 
                    encodedAddr = URLEncoder.encode(getAddress()); 
                } 
                String addSuffix=(getAddress()==null) ?"": ",address=" + encodedAddr; 
                oname=new ObjectName(cb.getName() + ":type=Connector,port="+ 
                        getPort() + addSuffix); 
                Registry.getRegistry(null, null) 
                    .registerComponent(this, oname, null); 
                controller=oname; 
            } catch (Exception e) { 
                log.error( "Error registering connector ", e); 
            } 
            log.debug("Creating name for connector " + oname); 
}

 
ConnectorMbean暴露了它的属性和Start、stop、pause、resume、init、destroy等方法。可以在Jconsole中对这些方法进行操作。
★ 3
daemon.start()Catalina.start()StandardServer.start()
下面是Catalina.start()代码片段。
(org.apache.catalina.core.StandardServer.start()) 

public void start() throws LifecycleException { 

        if (started) { 
            log.debug(sm.getString("standardServer.start.started")); 
            return; 
        } 

        //唤醒相关的生命周期监听者 
        lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null); 

        lifecycle.fireLifecycleEvent(START_EVENT, null); 
        started = true; 

        //启动我们定义的服务 
        synchronized (services) { 
            for (int i = 0; i < services.length; i++) { 
                if (services[i] instanceof Lifecycle) 
                    ((Lifecycle) services[i]).start(); 
            } 
        } 

        //唤醒相关的生命周期监听者 
        lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null); 

    }

 

Tomcat的配置文件Server.xml中的Server元素中定义了Listener元素,如下所示: 

<Server port="8005" shutdown="SHUTDOWN" debug="0"> 
... 
  <Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" 
            debug="0"/> 
...

 
它将给org.apache.catalina.core.StandardServer添加一个org.apache.catalina.mbeans.ServerLifecycleListener类型的监听器,当StandardServer实例启动的时候,会触发一个START_EVENT事件,如StandardServer类中定义的那样: 

public void start() throws LifecycleException { 
  ... 
  lifecycle.fireLifecycleEvent(START_EVENT, null); 
  ... 
}

 
StandardServer对象停止的时候,会触发STOP_EVENT事件,如stop方法中定义的那样: 

public void stop() throws LifecycleException { 
  ... 
  lifecycle.fireLifecycleEvent(STOP_EVENT, null); 
  ... 
}

 
这些事件会导致ServerLifecycleListener中的lifecycleEvent方法被提交。下面展示了lifecycleEvent方法。
(org.apache.catalina.mbeans.ServerLifecycleListener.lifecycleEvent()) 

public void lifecycleEvent(LifecycleEvent event) { 
        Lifecycle lifecycle = event.getLifecycle(); 
        if (Lifecycle.START_EVENT.equals(event.getType())) { 
            if (lifecycle instanceof Server) { 
                createMBeans(); 
... 
        } 
... 
else if (Lifecycle.STOP_EVENT.equals(event.getType())) { 
            try { 
                if (lifecycle instanceof Server) { 
                    destroyMBeans((Server)lifecycle); 
                } 
                if (lifecycle instanceof Service) { 
                    destroyMBeans((Service)lifecycle); 
                } 
  }

 

从上面的代码可以看出当lifecycleEvent被调用时,由于START_EVENT事件被触发,createMBeans方法被调用,Catalina中所有MBeans将会生成。当StandardServer关闭时,STOP_EVENT事件被触发,destroyMBeans方法被调用,所有的MBeans将被销毁。
1) START_EVENT事件被触发,lifecycleEvent(START_EVENT)被调用,它会调用createMBeans方法。
(org.apache.catalina.mbeans.ServerLifecycleListener.createMBeans()) 

protected void createMBeans() { 

        try { 
            MBeanFactory factory = new MBeanFactory(); 
            createMBeans(factory);※1 
            createMBeans(ServerFactory.getServer());※2 
        } catch (MBeanException t) { 
            Exception e = t.getTargetException(); 
            if (e == null) 
                e = t; 
            log.error("createMBeans: MBeanException", e); 
        } catch (Throwable t) { 
            log.error("createMBeans: Throwable", t); 
        } 
    }

 
※1
该方法使用MBeanUtil类给MBeanFactory创建一个ObjectName并将其向MBean服务器注册。 

protected void createMBeans(MBeanFactory factory) throws Exception { 
        // Create the MBean for the MBeanFactory 
        if (log.isDebugEnabled()) 
            log.debug("Creating MBean for MBeanFactory " + factory); 
        MBeanUtils.createMBean(factory); 
    }

 
※2
该方法会将org.apache.catalina.Server对象创建模型MBean,使用for循环来迭代StandardServer实例中的所有Service对象。 

protected void createMBeans(Server server) throws Exception { 

        //为Server自身创建MBean 
        if (log.isDebugEnabled()) 
            log.debug("Creating MBean for Server " + server); 
        //MBeanUtils.createMBean(server); 
        if (server instanceof StandardServer) { 
            ((StandardServer) server).addPropertyChangeListener(this); 
        } 

        // 为global NamingResources创建MBean(如果有的话) 
        NamingResources resources = server.getGlobalNamingResources(); 
        if (resources != null) { 
            createMBeans(resources); 
        } 

        //为每个子服务创建MBeans 
        Service services[] = server.findServices(); 
        for (int i = 0; i < services.length; i++) { 
            // FIXME - Warp object hierarchy not currently supported 
            if (services[i].getContainer().getClass().getName().equals 
                ("org.apache.catalina.connector.warp.WarpEngine")) { 
                if (log.isDebugEnabled()) { 
                    log.debug("Skipping MBean for Service " + services[i]); 
                } 
                continue; 
            } 
            createMBeans(services[i]); 
        } 

    }

 
4) createMBeans(Service service) 创建一个MBean实例并调用createMBeans方法来为该服务所有的连接器和引擎创建MBean对象
(org.apache.catalina.mbeans.ServerLifecycleListener.createMBeans(Service)) 

protected void createMBeans(Service service) throws Exception { 

        //为Service自身创建MBean 
        if (log.isDebugEnabled()) 
            log.debug("Creating MBean for Service " + service); 
        //MBeanUtils.createMBean(service); 
        if (service instanceof StandardService) { 
            ((StandardService) service).addPropertyChangeListener(this); 
        } 

        // 为对应的连接器创建MBeans(8080,8009两个端口) 
        Connector connectors[] = service.findConnectors(); 
        for (int j = 0; j < connectors.length; j++) { 
            createMBeans(connectors[j]); 
        } 

        // 为关联的Engine创建MBean 
        Engine engine = (Engine) service.getContainer(); 
        if (engine != null) { 
            createMBeans(engine); 
        } 

    }

 

5) createMBeans(engine)(org.apache.catalina.mbeans.ServerLifecycleListener.createMBeans(Engine)) 

protected void createMBeans(Engine engine) throws Exception { 

        //为Engine自身创建MBean 
        if (log.isDebugEnabled()) { 
            log.debug("Creating MBean for Engine " + engine); 
        } 
        //MBeanUtils.createMBean(engine); 
        engine.addContainerListener(this); 
        if (engine instanceof StandardEngine) { 
            ((StandardEngine) engine).addPropertyChangeListener(this); 
        } 

        //为关联的嵌套组件创建MBean 
        Realm eRealm = engine.getRealm(); 
        if (eRealm != null) { 
            if (log.isDebugEnabled()) 
                log.debug("Creating MBean for Realm " + eRealm); 
            //MBeanUtils.createMBean(eRealm); 
        } 

        // 为每个子Host创建MBeans 
        Container hosts[] = engine.findChildren(); 
        for (int j = 0; j < hosts.length; j++) { 
            createMBeans((Host) hosts[j]); 
        }

 
6) createMBeans(host) ((org.apache.catalina.mbeans.ServerLifecycleListener.createMBeans(Host)) 

protected void createMBeans(Host host) throws Exception { 

        //为Host自身创建MBeans 
        if (log.isDebugEnabled()) { 
            log.debug("Creating MBean for Host " + host); 
        } 
        //MBeanUtils.createMBean(host); 
        host.addContainerListener(this); 
        if (host instanceof StandardHost) { 
            ((StandardHost) host).addPropertyChangeListener(this); 
        } 

        //为关联的嵌套组件创建MBean 
        Realm eRealm = host.getParent().getRealm(); 
        Realm hRealm = host.getRealm(); 
        if ((hRealm != null) && (hRealm != eRealm)) { 
            if (log.isDebugEnabled()) 
                log.debug("Creating MBean for Realm " + hRealm); 
            //MBeanUtils.createMBean(hRealm); 
        } 

        //为每个子Context创建MBeans 
        Container contexts[] = host.findChildren(); 
        for (int k = 0; k < contexts.length; k++) { 
            createMBeans((Context) contexts[k]); 
        } 

    }

 

lifecycleEvent(START_EVENT)方法调用结束。调用会逐级返回, ((Lifecycle) services[i]).start()被调用。Deployer、GlobalRequestProcessor、JkHander、JkMain、JkWorkerEnv、Mapper、ThreadPool、Valve、ProtocolHandle等将会被注册。至此,Tomcat启动结束。JMX注册也完毕。

 

1
1
分享到:
评论
1 楼 jilen 2011-04-01  
个人感觉如果不是对JMX感兴趣,可以先跳过这部分,对其他源码阅读不怎么影响。我之前也被这些MBean困惑了N久,后面就直接无视了,准备等将来学习JMX再拿出来看看

相关推荐

    apache-tomcat-7.0.62-src和apache-tomcat-6.0.39-src的源码

    这个压缩包包含了两个版本的Tomcat源码:apache-tomcat-7.0.62-src和apache-tomcat-6.0.39-src,这两个版本分别代表了Tomcat在不同时间点的开发状态和技术特性。 首先,让我们从Apache Tomcat 6.0.39源码开始分析。...

    jmx监控weblogic,tomcat,websphere源码

    在本项目中,"jmx监控weblogic,tomcat,websphere源码"涉及了使用JMX来监控三个主流的Java应用服务器:WebLogic、Tomcat和WebSphere。这些服务器都是企业级应用部署的常见选择,对它们的监控对于确保系统性能、稳定性...

    apache-tomcat-9.0.8-src源码资源

    通过对`apache-tomcat-9.0.8-src`源码的深入研究,我们可以了解到Tomcat如何处理网络请求,怎样管理Web应用,以及如何实现各种高级特性。这对于开发者来说是一份宝贵的学习资料,可以帮助他们更好地优化应用程序,...

    apache-tomcat-6.0.29.zip

    8. **安全管理**:Tomcat支持角色基础的访问控制(RBAC),可以设置不同用户的访问权限,通过`tomcat-users.xml`配置用户和角色。 9. **日志系统**:Tomcat提供了详细的日志记录功能,帮助开发者调试和监控应用。...

    tomcat源码

    Apache Tomcat源码分析 Apache Tomcat是一款广泛应用的开源Java Servlet容器,它是Java EE Web应用程序的标准实现。Tomcat源码的深入理解对于Java Web开发者来说是至关重要的,它可以帮助我们了解HTTP服务器的工作...

    apache-tomcat-9.0.14-src源码

    对于初次接触Tomcat源码的开发者,可以从阅读`src/main/java`目录下的源码开始,重点关注`org.apache.catalina`包下的类,以及`org.apache.coyote`和`org.apache.jasper`等包。同时,`conf/server.xml`是配置整个...

    apache-tomcat-源码-lib包

    8. **JMX(Java Management Extensions)**:Tomcat使用JMX来提供管理和监控功能,如监控服务器状态、性能指标等。`org.apache.tomcat.util.modeler`包下的类涉及JMX的实现。 9. **国际化和本地化**:Tomcat支持多...

    Tomcat源码研究.pdf

    ### Tomcat源码研究知识点概览 #### 1.1 Catalina.bat脚本解析 - **脚本功能**:`catalina.bat`是Tomcat启动过程中的关键脚本之一,其主要作用在于构建合适的Java命令行参数,进而启动Tomcat服务。此脚本根据环境...

    tomcat6的源码

    5. **JMX(Java Management Extensions)**:Tomcat支持JMX,允许管理员监控和管理服务器状态。查看`jmx`目录下的源码可以了解如何使用JMX注册和暴露管理MBean。 6. **配置解析**:Tomcat的配置文件如`server.xml`...

    apache-tomcat-7.0.40-src源码

    8. **性能优化**:Tomcat源码分析可以帮助开发者了解如何优化性能,如调整线程池大小,启用NIO(非阻塞I/O)模式,减少内存泄漏等。 9. **扩展性**:Tomcat源码允许开发者自定义Valves(请求处理管道中的组件)、...

    apache-tomcat-9.0.54-src.zip

    - 调试Tomcat源码可以定位并解决运行时问题,例如性能瓶颈、内存泄漏或安全漏洞。 6. **扩展与定制** - Tomcat允许开发者自定义其行为,例如通过编写监听器、过滤器或servlet来扩展其功能。 - 可以通过编写自己...

    jakarta-tomcat-connectors-1.2.15-src.zip

    【标题】"jakarta-tomcat-connectors-1.2.15-src.zip" 是一个包含Apache Tomcat连接器源代码的压缩包,主要用于帮助开发者深入理解Tomcat的工作原理,并进行自定义或扩展。 【描述】提到的"jakarta_tomcat_...

    tomcat8.0源码

    8. **JMX(Java Management Extensions)** - JMX用于监控和管理Tomcat实例,包括内存使用、线程状态、MBean注册等。 9. **错误处理和调试** - 错误页面和异常处理:通过`web.xml`配置,可以自定义错误页面和异常...

    apache-tomcat-9.0.44.tar.gz

    标题中的"apache-tomcat-9.0.44.tar.gz"是一个特定版本的Tomcat源码包,这里的9.0.44指的是Tomcat的版本号,而".tar.gz"是Linux/Unix系统中常见的归档压缩格式,用于将多个文件打包成一个单一的文件以便于传输和存储...

    tomcat7源码下载

    《深入剖析Tomcat7源码》 Tomcat7是一款广泛使用的开源Java Servlet容器,它实现了Java EE中的Web应用服务器标准,尤其是Servlet和JSP规范。源码下载是开发者深入理解其内部工作原理的重要途径,本篇文章将围绕...

    tomcat源码学习之环境搭建

    8. **JMX监控**:Tomcat使用Java Management Extensions (JMX) 提供监控和管理功能。通过MBeans(Managed Beans)可以获取服务器状态、配置和性能数据。 9. **日志系统**:Tomcat使用`org.apache.juli`包实现日志...

    Tomcat深入剖析pdf+源码(Tomcat运行原理)

    9. **JMX管理**:通过Java Management Extensions(JMX),开发者可以远程监控和管理Tomcat的运行状态,如查看线程池状态、内存使用情况等。 10. **性能优化**:优化Tomcat涉及调整线程池大小、缓存设置、减少上...

    Tomcat源码 学习java很好的东东 apache-tomcat-6.0.26-src

    10. **性能优化**:Tomcat源码提供了很多可调整的参数,通过对这些参数的调整,可以优化内存使用、减少响应时间等,提升整体性能。 通过深入学习和理解"apache-tomcat-6.0.26-src"源码,开发者不仅可以提高Java Web...

Global site tag (gtag.js) - Google Analytics