`
toking79
  • 浏览: 22665 次
  • 性别: 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再拿出来看看

相关推荐

    jmx监控weblogic,tomcat,websphere源码

    java项目,自己做的项目利用jmx监控weblogic,tomcat,websphere源码

    Tomcat源码研究.pdf

    Tomcat源码研究.pdf。Catalina脚本解析,Tomcat启动遇到的常见问题,架构探讨,JMX在tomcat中的应用,容器初探,生命周期

    tomcat学习源码

    资源是关于tomcat深入剖析的源码. ...本书从最基本的HTTP请求开始,直至使用JMX技术管理Tomcat中的应用程序,逐一剖析Tomcat的基本功能模块,并配以示例代码,使读者可以逐步实现自己的Web服务器。

    Tomcat源码分析

    总体架构:1、面向组件架构2、基于JMX3、事件侦听tomcat代码看似很庞大,但从结构上看却很清晰和简单,它主要由一堆组件组成,如Server、Service、Connector等,并基于JMX管理这些组件,另外实现以上接口的组件也...

    apache-commons源码及jar文件

    Commons-Modeler 提供了建模兼容JMX规范的 Mbean的机制. Net Net 是一个网络工具集,基于 NetComponents 代码,包括 FTP 客户端等等。 Pool Commons-Pool 提供了通用对象池接口,一个用于创建模块化对象池的工具包...

    JAVA上百实例源码以及开源项目源代码

    Java 源码包 Applet钢琴模拟程序java源码 2个目标文件,提供基本的音乐编辑功能。编辑音乐软件的朋友,这款实例会对你有所帮助。 Calendar万年历 1个目标文件 EJB 模拟银行ATM流程及操作源代码 6个目标文件,EJB来...

    JAVA上百实例源码以及开源项目

    8个目标文件 简单 JavaScript万年历 显示出当前时间及年份,还可以选择年份及月份和日期 Java编写的HTML浏览器 一个目标文件 摘要:Java源码,网络相关,浏览器  Java编写的HTML浏览器源代码,一个很简单甚至不算是...

    repo:小虫代码资源开放库

    |-&gt;|-&gt;(抽离tomcat源码之生命周期) |-&gt;|-&gt;(二进制文件加密) |-&gt; (jmx使用演示) |-&gt; (mongodb使用演示) |-&gt; (GUI聊天器-客户端+服务端原始码) |-&gt; (自己实现动态代理) |-&gt; (json与地图,列表,对象之间...

    xmljava系统源码-mountain:山

    java系统源码 mountain 工程 后端工程启动后访问URL: 访问url: 更新日期-20200415 buglist 权限管理一些bug修改 newlist 用户管理添加昵称 更新日期-20200326 buglist 在idea中执行package打包时,打包2次,是因为...

    《程序天下:J2EE整合详解与典型案例》光盘源码

    1.4.10 JMX(Java分布式管理) 1.4.11 JACC(Java容器授权合同) 1.4.12 JCA(Java连接器体系) 1.5 小结 第二章 MVC模式介绍 2.1 MVC模式概述 2.1.1 MVC模式的设计思想 2.1.2 MVC模式的处理过程 2.2 Model规范 ...

    java开源包8

    MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的Java包,主要特点是多线程、调度、JMX管理和批量执行报表,执行历史等。 SIP协议包 jSIP.tar jSIP这个Java包目标是用Java实现SIP(SIP:...

    java卡牌游戏源码-HTTPServer:基于Netty、JSON-RPC的分布式弱联网游戏服务端

    java卡牌游戏源码 弱联网服务端架构 HTTPServer说明 此Demo为个人兴趣所写,是本人通过半年多服务端学习的一次大胆尝试,将之前学到的很多知识都融合在一起,除了对以前的知识整合之外,也不断进行改变和创新!目前...

    搞定J2EE:STRUTS+SPRING+HIBERNATE整合详解与典型案例 (2)

    1.4.10 JMX(Java分布式管理) 1.4.11 JACC(Java容器授权合同) 1.4.12 JCA(Java连接器体系) 1.5 小结 第二章 MVC模式介绍 2.1 MVC模式概述 2.1.1 MVC模式的设计思想 2.1.2 MVC模式的处理过程 2.2 Model规范 ...

    搞定J2EE:STRUTS+SPRING+HIBERNATE整合详解与典型案例 (1)

    1.4.10 JMX(Java分布式管理) 1.4.11 JACC(Java容器授权合同) 1.4.12 JCA(Java连接器体系) 1.5 小结 第二章 MVC模式介绍 2.1 MVC模式概述 2.1.1 MVC模式的设计思想 2.1.2 MVC模式的处理过程 2.2 Model规范 ...

    搞定J2EE:STRUTS+SPRING+HIBERNATE整合详解与典型案例 (3)

    1.4.10 JMX(Java分布式管理) 1.4.11 JACC(Java容器授权合同) 1.4.12 JCA(Java连接器体系) 1.5 小结 第二章 MVC模式介绍 2.1 MVC模式概述 2.1.1 MVC模式的设计思想 2.1.2 MVC模式的处理过程 2.2 Model规范 ...

    java开源包1

    MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的Java包,主要特点是多线程、调度、JMX管理和批量执行报表,执行历史等。 SIP协议包 jSIP.tar jSIP这个Java包目标是用Java实现SIP(SIP:...

    java开源包10

    MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的Java包,主要特点是多线程、调度、JMX管理和批量执行报表,执行历史等。 SIP协议包 jSIP.tar jSIP这个Java包目标是用Java实现SIP(SIP:...

    java开源包2

    MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的Java包,主要特点是多线程、调度、JMX管理和批量执行报表,执行历史等。 SIP协议包 jSIP.tar jSIP这个Java包目标是用Java实现SIP(SIP:...

Global site tag (gtag.js) - Google Analytics