首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

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

2012-08-28 
Tomcat源码系列8--Tomcat的JMX管理2前面讲到了JMX的体系,下面从Tomcat源代码启动过程分析MBeans组件注册到

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

热点排行