Tomcat架构解析
1 Tomcat总体架构
Tomcat作为Servlet服务器,其结构非常复杂,但是Tomcat设计的非常的模块化,从总体理解Tomcat的架构不难。
一个Server实例就表示一个Tomcat。一个Server可以包含至少一个Service,用于提供服务。
Service主要包含两个部分:Connector和Container。一个Service可以包含多个Connector,但是只能包含一个Container。
Connector用于处理Socket连接,将Socket与Request和Response进行转换。Tomcat提供了Http和AJP(用于与Apache服务器通信)等协议实现多个Connector。
Container是用于处理具体的业务容器,Tomcat提供了如下四种Container:
-
Engine: 表示整个Servlet引擎,Engine为最高级别的容器。尽管Engine不是直接处理请求的容器却是获得目标容器的入口。
-
Host:表示Engine中的虚拟主机,与一个服务器的网络名有关,如域名等。客户端可以使用这个网络名连接服务器,这个名称必须要在DNS服务器上注册。
-
Context:用于表示ServletContext,在Servlet规范中,一个ServletContext表示一个Web应用。
-
Wrapper:表示Web应用中定义的Servlet。
通过下面这张图展示了Tomcat中核心组件的关系:
使用Container代表容器,Engine、Host、Context、Wrapper都是Container的子容器,Container可以维护子容器。backgroundProcess()方法针对后台处理,并且其基础抽象类(ContainerBase)确保在启动组件的同时,异步启动后台处理。
Tomcat还包含其他一些辅助的组件,如下:
-
manager: 用于管理session组件, Context中的Session就是通过Manager管理。
-
logger:日志组件。默认使用JUL日志框架。
-
loader: Context用于管理和加载应用的资源。
-
pipline:Tomcat采用管道的形式在Container之间实现调用。
-
valve:管道中的阀门,判断是否继续向下执行。
-
realm:用于实现Tomcat中的权限管理。
-
Cluster:实现Tomcat集群管理,Session的复制。
-
Listener:Tomcat中用于实现监听的组件,在Tomcat中大量存在。
另外Tomcat还实现了JNDI和JMX。Tomcat中几乎所有的组件都通过JMX管理。
2 Connector架构分析
Connector用于接受请求并将请求封装成Request和Response,然后交给Container进行处理,Container处理完之后在交给Connector返回给客户端。
Connector就是使用ProtocolHandler来处理请求的,不同的ProtocolHandler代表不同的连接类型,比如:Http11Protocol使用的是普通Socket来连接的,Http11NioProtocol使用的是NioSocket来连接的。
其中ProtocolHandler由包含了三个部件:Endpoint、Processor、Adapter。
-
Endpoint用来处理底层Socket的网络连接,Processor用于将Endpoint接收到的Socket封装成Request,Adapter用于将Request交给Container进行具体的处理。
-
Endpoint由于是处理底层的Socket网络连接,因此Endpoint是用来实现TCP/IP协议的,而Processor用来实现HTTP协议的,Adapter将请求适配到Servlet容器进行具体的处理。
-
Endpoint的抽象实现AbstractEndpoint里面定义的Acceptor和AsyncTimeout两个内部类和一个Handler接口。Acceptor用于监听请求,AsyncTimeout用于检查异步Request的超时,Handler用于处理接收到的Socket,在内部调用Processor进行处理。
3 Container架构分析
Container用于封装和管理Servlet,以及具体处理Request请求。Container通过pipeline处理请求。每个Pipeline都有特定的Valve,而且是在管道的最后一个执行,这个Valve叫做BaseValve,BaseValve是不可删除的。在上层容器的管道的BaseValue中会调用下层容器的管道。
Container容器对应的BaseValve分别是:StandardEngineValve,StandardHostValve,StandardContextValve,StandardWrapperValve。
Pipeline调用流程:
-
Connector在接收到请求后会首先调用最顶层容器的Pipeline来处理,这里的最顶层容器的Pipeline就是EnginePipeline(Engine的管道);
-
在Engine的管道中依次会执行EngineValve1、EngineValve2等等,最后会执行StandardEngineValve,在StandardEngineValve中会调用Host管道,然后再依次执行Host的HostValve1、HostValve2等,最后在执行StandardHostValve,然后再依次调用Context的管道和Wrapper的管道,最后执行到StandardWrapperValve;
-
当执行到StandardWrapperValve的时候,会在StandardWrapperValve中创建FilterChain,并调用其doFilter方法来处理请求,这个FilterChain包含着我们配置的与请求相匹配的Filter和Servlet,其doFilter方法会依次调用所有的Filter的doFilter方法和Servlet的service方法;
-
当所有的Pipeline-Valve都执行完之后,并且处理完了具体的请求,这个时候就可以将返回的结果交给Connector了,Connector在通过Socket的方式将结果返回给客户端。