tomcat阅读第七篇(tomcat 组件之Server)
从tomcat文档,或者更具上篇我们分析的Lifecycle继承关系或者查看Server.xml配置文件可以知道,在Lifecycle继承链下tomcat有几大组件,Server、Service、Context、Engine、Host,当然Lifecycle继承链下还有其他组件。
从分析Catalina那篇可以知道,Catalina的方法会调用Server的对应的start、stop等等方法,
而从上篇知道LifecycleBase会有startInternal等回调方法,通观StandServer可以发现有XXInternal方法,这篇主要关注的就是这几个方法。
startInternal和await方法:
为什么把这两个方法放一起,可以回顾下Catalina那篇,Catalina的Start方法
public void start() { getServer().start(); …………… getServer().destroy(); ……….. //BootStrap调用Catalina setAwait设置await为true if (await) { await(); // getServer().await(); stop(); } }
等分析完Server的startInternal方法和await方法可以回头总结下Catalina的方法。
startInternal 方法:
protected void startInternal() throws LifecycleException { //触发CONFIGURE_START_EVENT事件,注册这个事件的监听器会调用 fireLifecycleEvent(CONFIGURE_START_EVENT, null); setState(LifecycleState.STARTING); //调用globalNamingResources的start globalNamingResources.start(); //调用services的start方法 synchronized (servicesLock) { for (int i = 0; i < services.length; i++) { services[i].start(); } } }
这里面有几个疑问,globalNamingResources和services的什么时候创建的,Digester那篇分析可以知道,在Catalian.load方法中给Digester设置rule,
然后解析来生成对象链。现在我们回头去关注跟globalNamingResources和services有关的部分
protected Digester createStartDigester() { …………. ………… //Server部分,创建StandardServer对象,调用Catalina的setServer设值 digester.addObjectCreate("Server", "org.apache.catalina.core.StandardServer", "className"); digester.addSetProperties("Server"); digester.addSetNext("Server", "setServer", "org.apache.catalina.Server"); // Server/GlobalNamingResources部分,创建NamingResourcesImpl对象调用StandardServer的setGlobalNamingResources设值,并且给NamingResourcesImpl对象设值Server.xml上相对应的properties digester.addObjectCreate("Server/GlobalNamingResources", "org.apache.catalina.deploy.NamingResourcesImpl"); digester.addSetProperties("Server/GlobalNamingResources"); digester.addSetNext("Server/GlobalNamingResources", "setGlobalNamingResources", "org.apache.catalina.deploy.NamingResourcesImpl"); ……………… ………….. // Server/Service部分, 创建StandardService,调用StandardService的addService方法设值 digester.addObjectCreate("Server/Service", "org.apache.catalina.core.StandardService", "className"); digester.addSetProperties("Server/Service"); digester.addSetNext("Server/Service", "addService", "org.apache.catalina.Service"); ………………………… }
现在简单看下上面提到的方法
public void setGlobalNamingResources //设置globalNamingResources属性,出发PropertyChange事件 (NamingResourcesImpl globalNamingResources) { NamingResourcesImpl oldGlobalNamingResources = this.globalNamingResources; this.globalNamingResources = globalNamingResources; this.globalNamingResources.setContainer(this); support.firePropertyChange("globalNamingResources", oldGlobalNamingResources, this.globalNamingResources); } public void addService(Service service) { //添加新service进services数组,设置service的server属性 service.setServer(this); synchronized (servicesLock) { Service results[] = new Service[services.length + 1]; System.arraycopy(services, 0, results, 0, services.length); results[services.length] = service; services = results; if (getState().isAvailable()) { try { //启动service service.start(); } catch (LifecycleException e) { // Ignore } } support.firePropertyChange("service", null, service); } }
现在回头看startInternal 方法,调用GlobalNamingResources和service的start方法。这两个对象后面可以分析,重点是StandardService,这篇主要看Server。
avwait方法:
启动一个ServerSocket,监听Catalina的stopServer方法发送的SHUTDWON,当监听到SHUTDOWN ,await方法将break while,停止阻塞。
回头看Catalina的start方法,大致逻辑,调用server Start方法,然后调server Awati方法keep main thread alive。
stopInternal方法(当将tomcat作为service的时候,停止服务将调用stopInternal方法):
protected void stopInternal() throws LifecycleException { setState(LifecycleState.STOPPING); //触发CONFIGURE_STOP_EVENT事件 fireLifecycleEvent(CONFIGURE_STOP_EVENT, null); //停止service for (int i = 0; i < services.length; i++) { services[i].stop(); } //停止globalNamingResources globalNamingResources.stop(); stopAwait();//设置stopAwait为true }
initInternal 方法和destroyInternal 方法:
initInternal方法:
protected void initInternal() throws LifecycleException { super.initInternal(); //注册StringCache为JMX onameStringCache = register(new StringCache(), "type=StringCache"); // 注冊factory为JMX MBeanFactory factory = new MBeanFactory(); factory.setContainer(this); onameMBeanFactory = register(factory, "type=MBeanFactory"); //调用resource的init方法 globalNamingResources.init(); // Populate the extension validator with JARs from common and shared class loaders if (getCatalina() != null) { ClassLoader cl = getCatalina().getParentClassLoader(); while (cl != null && cl != ClassLoader.getSystemClassLoader()) { if (cl instanceof URLClassLoader) { URL[] urls = ((URLClassLoader) cl).getURLs(); for (URL url : urls) { if (url.getProtocol().equals("file")) { try { File f = new File (url.toURI()); if (f.isFile() && f.getName().endsWith(".jar")) { ExtensionValidator.addSystemResource(f); } } catch (URISyntaxException e) { // Ignore } catch (IOException e) { // Ignore } } } } cl = cl.getParent(); } } // Initialize our defined Services for (int i = 0; i < services.length; i++) { services[i].init(); }
destroyInternal 方法:
protected void destroyInternal() throws LifecycleException { //destroy service for (int i = 0; i < services.length; i++) { services[i].destroy(); } // destroy resource globalNamingResources.destroy(); //注销onameMBeanFactory JMX unregister(onameMBeanFactory); //注销onameStringCache JMX unregister(onameStringCache); super.destroyInternal(); }
总结:
当作为CMD start 启动时,start方法再调用service的star后会因为await阻塞,当CMD stop时,Server的await启动的ServerSocket会监听Catalina的stopServer方法发送的SHUTDOWN,当监听到SHUDOWN,while break,然后调用stop,destroy。
Bootstrap.init->Catalina.Load->Server.InitInternal,
CMD –start Bootstrap.main-> Catalina.Start->Server.StartInternal,
CMD –stop Bootstrap.main-> Catalina.StopServer导致start的阻塞while break->Server.StopInternal+Server.DestroyInternal,
当作为service的时候,
Bootstrap.init->Catalina.Load->Server.InitInternal,
Bootstrap.main->Catalina.Start->Server.StartInternal,
Bootstrap.main->Catalina.Stop->Server.StopInternal+Server.DestroyInternal,