用了两天事件梳理Tomcat的启动过程,主要参考了文章http://www.ibm.com/developerworks/cn/java/j-lo-tomcat1/。
Tomcat启动主要涉及到下面这几个类:
Bootstrap,Catalina,StandardServer,StandardService,Connector,StandardEngine。整体架构如下:
org.apache.catalina.startup.Bootstrap
1. 初始化classloader
initClassLoaders()
2. Bootstrap通过反射关联Catalina类
Class<?> startupClass =
catalinaLoader.loadClass
("org.apache.catalina.startup.Catalina");
3. 启动
daemon.setAwait(true);
daemon.load(args);
daemon.start();
org.apache.catalina.startup.Catalina
/**
* Startup/Shutdownshell program for Catalina. Thefollowing command line
*/
tomcat对外的控制接口,在Bootstrap类中通过反射调用Catalina的方法。
Load-> start-> await-> stop
org.apache.catalina.core.StandardServerextends LifecycleMBeanBase implements Server
Server 要完成的任务很简单,就是要能够提供一个接口让其它程序能够访问到这个Service 集合、同时要维护它所包含的所有Service 的生命周期,包括如何初始化、如何结束服务、如何找到别人要访问的 Service。
addService-> initInternal-> startInternal-> await->stopInternal
org.apache.catalina.core.StandardServiceextends LifecycleMBeanBase implements Service
Service 只是在 Connector 和Container 外面多包一层,把它们组装在一起,向外面提供服务,一个 Service 可以设置多个Connector,但是只能有一个Container 容器。
addConnector-> initInternal-> startInternal-> stopInternal
org.apache.catalina.connector.Connectorextends LifecycleMBeanBase
负责接收浏览器的发过来的 tcp 连接请求,创建一个 Request 和Response 对象分别用于和请求端交换数据,然后会产生一个线程来处理这个请求并把产生的Request 和Response 对象传给处理这个请求的线程,处理这个请求的线程就是Container 组件要做的事了。
构造在org.apache.catalina.startup.ConnectorCreateRule.begin中。
initInternal-> startInternal
org.apache.coyote.http11.Http11Protocol
org.apache.coyote.ajp.AjpProtocol
在Connector()中通过反射构造。setAdapter-> init-> start
Start后建立新线程完成socket通信。
org.apache.catalina.core.StandardEngineextends ContainerBase implements Engine
Container 是容器的父接口,所有子容器都必须实现这个接口,Container 容器的设计用的是典型的责任链的设计模式,它有四个子容器组件构成,分别是:Engine、Host、Context、Wrapper,这四个组件不是平行的,而是父子关系,Engine包含Host,Host 包含 Context,Context 包含Wrapper。通常一个Servlet class 对应一个 Wrapper,如果有多个 Servlet 就可以定义多个Wrapper,如果有多个Wrapper 就要定义一个更高的Container 了。
启动成功后建立新线程,处理所有容器的事件。
至此,tomcat就启动好了。流程图如下:
这时存在4个线程:
主线程监听“SHUTDOWN”命令;Container线程处理容器逻辑;HTTP线程处理外界连接;AJP线程用来与apache服务器通信,实现负载均衡。