Tomcat的顶层结构
Tomcat的顶层容器叫Server,代表整个服务器。Server至少包含一个service,service包含Connector和Containner。
Connector处理连接相关的事情,提供socket和request、response的转换,可以有多个
Containner用于封装管理Servlet,具体处理request的请求,只能有一个

org.apache.catalina.startup.Catalina类是整个tomcat的管理类,有load、start、stop分别管理整个服务器的生命周期,load方法根据conf/server.xml文件创建Server并调用Server的init方法初始化。
Catalina中的await方法直接调用Server的await方法进入循环,让主线程不会退出。
Tomcat的入口main方法在org.apache.catalina.startup.Bootstrap中,Bootstrap的作用类似一个CatalinaAdaptor,具体处理过程还是由Catalina来完成,这样做的好处是把启动的入口和具体的管理类分开,从而更方便的创建出多种启动方式,每种启动方式只需要写一个相应的CatalinaAdaptor就可以。
Tomcat的生命周期管理
Tomcat通过org.apache.catalina.Lifecycle接口统一管理生命周期,所以组建的生命周期都要实现Lifecycle接口,Lifecycle总共做四件事:
定义13个String类型的常量,用于
LifecycleEvent事件的type属性定义3个管理监听器的方法
addLifecycleListener、findLifecycleListeners、removeLifecycleListener,用来添加查找和删除LifecycleListener类型的监听器定义4个生命周期的方法init、start、stop、destroy,用于执行生命周期阶段的操作
定义获取当前状态的2个方法
getState和getStateName,getState返回值LifecycleState是枚举类型,里边列举了生命周期的各个节点
org.apache.catalina.util.LifecycleBase类为Lifecycle接口提供了默认实现:监听器管理是专门使用了LifecycleSuppport类来完成的;生命周期方法init、start、stop、destroy中设置了相应的状态并调用相应的模版方法initInternal、startInternal、stopInternal、destroyInternal,模版方法由子类具体实现
Containner分析
Containner一共有4个子接口Engine、Host、Context、Wrapper和一个默认实现类ContainnerBase,每个子接口都是一个容器,这4个字容器有一个对应的StandardXXX实现类,并且这些实现类都继承ContainnerBase类。通常使用的Servlet封装在Wrapper中。

Engine管理多个Host,一个Service只能有一个Engine
每个Host代表一个虚拟主机
每个Context代表一个应用
每个Wrapper封装着一个Servlet
Containner的启动是通过init和start方法来完成的,这俩个方法会在tomcat起动时被Service调用,Containner也是按照tomcat的生命周期来管理的,init和start方法调用initInternal和startInternal方法来具体处理,但Containner和tomcat整体结构启动的方式稍微不一样:
Containner4个子容器的共同父类
ContainnerBase定义了Containner容器的initInternal和startInternal方法通用处理内容除了最顶层容器的init是被Service调用,子容器的init方法不是在容器中逐层循环调用,而是在执行Start方法后通过状态判断没有初始化后调用
Start方法除了在父容器中的
startInternal中调用,还会在父容器的添加子容器的addChild中调用,因为Context和Wrapper是动态添加的(我们在站点目录下放一个文件夹活着war包就可以添加一个context,在web.xml中配置一个Servlet就可以添加一个Wrapper),所以Context和Wrapper是在容器启动过程中动态查找并添加到相应的父容器中的。
ContainnerBase的initInternal方法主要初始化ThreadPoolExecutor类型的startStopExecutor属性,用于管理启动和关闭线程,代码如下:protected void initInternal() throws LifecycleException {
BlockingQueue<Runnable> startStopQueue = new LinkedBlockingQueue<>();
startStopExecutor = new ThreadPoolExecutor(
getStartStopThreadsInternal(),
getStartStopThreadsInternal(), 10L, TimeUnit.SECONDS,
startStopQueue,
new StartStopThreadFactory(getName() + "-startStop-"));
startStopExecutor.allowCoreThreadTimeOut(true);
super.initInternal();
}
ThreadPoolExecutor继承自Executor用于管理线程,特别是Runable类型的线程。
ContainnerBase的startInternal方法主要做5件事
如果有
Cluster和Realm则调用start方法(Cluster用于配置集群,Realm是tomcat的安全域,管理资源的访问权限)调用所以子容器的start方法启动子容器
调用管道中的
Value的start方法来启动管道启动完成后将生命周期设置为
LifecycleState.STARTING状态启动后台线程定期做一些事情
Connector分析
Connector用于接收请求并将请求封装成Request和Response来具体处理,最底层是使用Socket连接,Request和Response是按照HTTP协议来封装,所以Connctor同时实现了TCP/IP协议和HTTP协议,Request和Response封装完以后交给Containner处理,Containner是Servlet容器,Containner处理完交给Connector,最后Connector使用Socket将处理结果返回给客户端,整个请求就处理完了。
Connctor中具体是用ProtocolHandler处理请求的,不同的ProtocolHandler代表不同的连接类型,比如Http11NioProtocol是使用NioSocket来连接的。
ProtocolHandler有3个重要的组件:
EndPoint用于处理底层Socket的连接Processor用于将EndPoint接收的Socket封装成RequestAdapter用于将封装好的Request交给Containner进行具体处理

ProtocolHandler接口的抽象实现类AbstractProtocol分2种类型Ajp和HTTP,默认配置中的org.apache.coyote.http11.Http11NioProtocol使用HTTP1.1协议,TCP层使用NioSocket来传输数据。
Http11NioProtocol构造函数中创建NioEndPoint类型的EndPoint,并新建Http11ConnectionHandler类型的Handler然后设置到EndPoint中。
处理TCP/IP协议的EndPoint
EndPoint用于处理具体连接和传输数据,NioEndPoint继承自org.apache.tomcat.util.net.AbstractEndPoint,在EndPoint中新增Poller和SocketProcessor内部类,NioEndPoint的init和start方法在父类AbstractEndPoint中,主要调用模板方法bind和startInternal,这俩个方法在NioEndPoint中具体实现
处理HTTP协议的Processor
Processor用于处理应用层HTTP协议,Http11Processor类的process方法定义在其父类AbstractProcessorLight中,它会接着调用service抽象方法处理请求,Http11Processor类实现了自己的service方法
适配器Adapter
Adapter只有一个实现类org.apache.catalina.connector包下的CoyoteAdapter类。Http11Processor类的service方法会调用Adapter的service方法来调用Containner管道中的invoke方法处理请求,将原来创建的org.apache.coyto包下的Request和Response封装成org.apache.catalina.connector的Request和Responseconnector.getService().getContainer().getPipeline().getFirst().invoke(request, response);