整体架构
Tomcat中最外层的容器是Server,代表整个服务器,一个Server包含至少一个Service,用于提供服务。
Service主要包含两个部分:Connector和Container。Tomcat的核心就是这两个组件,他们的作用如下:
- Connector用于处理连接相关的操作,并提供Socket与Request和Response的转化;
- Container用于封装和管理Servlet,处理Request请求;
一个Tomcat中只有一个Server,一个Server可以包含多个Service,一个Service只有一个Container和有多个Connectors。Service存活在Server中,整个Tomcat的生命周期由Server控制。
例如同时提供Http和Https链接,或者提供向相同协议下不同端口的连接
框架中的层级关系还可以通过server.xml配置文件看出来,下图是删除了注释内容之后的一个完整server.xml配置文件(Tomcat版本8.0)
详细的配置文件文件内容可以到Tomcat官网查看:http://tomcat.apache.org/tomcat-8.0-doc/index.html
Server标签设置的端口号为8005,shutdown=”SHUTDOWN”表示在8005端口监听SHUTDOWN命令,如果接收到了就会关闭Tomcat。一个Server有一个或者多个Service。
server.xml配置文件还可以通过下边的结构图的展现:
图示Service左边的内容都属于Container的,Service下边是Connector
两大核心Connector和Container的关系
Connector最底层使用的是Socket来进行连接的,Request和Response按照HTTP协议来封装,所以Connector同时实现了TCP/IP协议和HTTP协议。一个请求发送到Tomcat后,首先经过Service,然后会交给Connector,Connector接收请求并封装为Request和Response来具体处理,Request和Response封装完之后再交由Container进行处理,Container处理完请求之后再返回给Connector,最后再由Connector通过Socket将处理的结果返回给客户端,请求处理完毕。
Connector结构如下图:
Connector使用ProtocolHandler来处理请求,不同的ProtocolHandler代表不同连接类型。比如:
- Http11Protocol使用的是普通Socket来连接,
- Http11NioProtocol使用的是NioSocket来连接的。
ProtocolHandler包含了三个部件:Endpoint、Processor、Adapter。
- Endpoint实现了TCP/IP协议,用来处理底层Socket的网络连接。
- Processor实现了HTTP协议,用于将Endpoint接收到的Socket封装成Request。
- Adapter将Request交给Container适配到Servlet容器进行具体的处理。
Endpoint的抽象实现AbstractEndpoint里面定义了Acceptor和AsyncTimeout两个内部类和一个Handler接口。Acceptor用于监听请求,AsyncTimeout用于检查异步Request超时,Handler用于处理接收到的Socket,在内部调用Processor进行处理。
Container结构如下图:
Container用于封装和管理Servlet,以及具体处理Request请求。在Container内部包含了4个子容器,分别是
- Engine:引擎
- Host:主机
- Context:上下文
- Wrapper:包装器
Engine:表示整个Catalina的Servlet引擎·
Host:表示一个拥有数个上下文的虚拟主机·
Context:表示一个Web应用,一个Context包含一个或多个Wrapper·
Wrapper:表示一个独立的Servlet。一个Context有一个或多个Wrapper,而Wrapper作为容器层次中的最底层,不能包含子容器。
tomcat文件目录对照
Context表示一个应用,Tomcat中默认配置下webapps里的每一个文件夹都是一个Context,其中ROOT目录中存放着主应用,其他目录存放着子应用,而整个webapps就是一个Host站点。
我们访问应用,如果是ROOT下的则直接使用域名就可以访问,例如:www.xxx.com,如果是Host(webapps)下的其他应用,则可以使用www.xxx.com/docs进行访问,默认指定的根应用(ROOT)是可以进行设定的,只不过Host站点下默认的主应用是ROOT。
Container处理请求是使用Pipeline-Valve(阀)管道来处理的。Pipeline-Valve采用责任链模式,即一个请求处理的过程中有很多处理者依次对请求进行相应处理,一个处理完之后将处理后的请求返回,下一个处理继续。
Pipeline-Valve使用的责任链模式有两个特点:
- 每个Pipeline都有特定的Valve,而且是在管道的最后一个执行,这个Valve叫做BaseValve,BaseValve是不可删除的。
- 在上层容器的管道的BaseValve中会调用下层容器的管道。
Pipeline的处理流程图如下:
Container包含的四个子容器对应的BaseValve分别在:StandardEngineValve,StandardHostValve,StandardContextValve,StandardWrapperValve。
- Connector在接收到请求后会首先调用EnginePipeline,在Engine的管道中依次执行,按箭头指向最后执行到WrapperPipeline的StandardWrapperValve。
- 最后在StandardWrapperValve中创建FilterChain,这个FilterChain包含我们配置的与请求相匹配的Filter和Servlet,其doFilter方法会依次调用所有Filter的doFilter方法和Servlet的service方法。
- 当所有的Pipeline-Valve都执行完之后就将返回的结果交给Connector,Connector再通过Socket的方式将结果返回给客户端。
至此,我们已经对Tomcat的基本架构和执行流程有了大致的了解。