Tomcat.基础.架构

整体架构

Tomcat.基础.架构

Tomcat中最外层的容器是Server,代表整个服务器,一个Server包含至少一个Service,用于提供服务。

 

Service主要包含两个部分:Connector和Container。Tomcat的核心就是这两个组件,他们的作用如下:

  1. Connector用于处理连接相关的操作,并提供Socket与Request和Response相关的转化; 
  2. Container用于封装和管理Servlet,以及具体处理Request请求;

 

一个Tomcat中只有一个Server,一个Server可以包含多个Service,一个Service只有一个Container和有多个Connectors,这是因为一个服务可以有多个连接。例如同时提供Http和Https链接,或者提供向相同协议下不同端口的连接,如下图所示:

 

Tomcat.基础.架构

 

多个 Connector 和一个 Container 组成一个 Service,并对外提供服务,但是 Service 必须要有一个存活的环境,即最外层的 Server,所以整个 Tomcat 的生命周期由 Server 控制。框架中的层级关系还可以通过server.xml配置文件看出来,下图是删除了注释内容之后的一个完整的server.xml配置文件(Tomcat版本8.0)

 

Tomcat.基础.架构

详细的配置文件文件内容可以到Tomcat官网查看:http://tomcat.apache.org/tomcat-8.0-doc/index.html

 

Server 标签设置的端口号为8005,shutdown=”SHUTDOWN” 表示在8005端口监听 SHUTDOWN 命令,如果接收到了就会关闭 Tomcat。一个 Server有一个 Service,当然还可以配置多个。

 

server.xml 配置文件还可以通过下边的一张结构图的展现:

Tomcat.基础.架构

图示 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的结构图:

Tomcat.基础.架构

  1. Connector 如何接受请求?
  2. Connector 如何将请求封装成 Request 和 Response?
  3. 封装完 Request 和 Response 如何交给 Container 进行处理?
  4. Container 处理完之后如何交给 Connector 并返回给客户端?

 

Connector 使用 ProtocolHandler 来处理请求,不同的 ProtocolHandler 代表不同连接类型,比如:Http11Protocol 使用的是普通 Socket 来连接,Http11NioProtocol使用的是NioSocket来连接的。

 

ProtocolHandler 包含了三个部件:Endpoint、Processor、Adapter

  1. Endpoint 实现了 TCP/IP 协议,用来处理底层 Socket 的网络连接。
  2. Processor 实现了 HTTP 协议,用于将Endpoint 接收到的 Socket 封装成 Request。
  3. Adapter 将 Request 交给 Container 适配到 Servlet 容器进行具体的处理。

 

Endpoint的抽象实现AbstractEndpoint里面定义了Acceptor和AsyncTimeout 两个内部类和一个 Handler 接口。Acceptor 用于监听请求,AsyncTimeout用于检查异步 Request 超时,Handler 用于处理接收到的 Socket,在内部调用 Processor 进行处理。

 

Container结构图如下:

Tomcat.基础.架构

 

Container用于封装和管理Servlet,以及具体处理Request请求。在 Container 内部包含了4个子容器,分别是:

  1. Engine:引擎
  2. Host:主机
  3. Context:上下文
  4. Wrapper:包装器

 

Engine:表示整个 Catalina 的 Servlet 引擎 · Host:表示一个拥有数个上下文的虚拟主机 · Context:表示一个 Web 应用,一个 Context 包含一个或多个 Wrapper · Wrapper:表示一个独立的 Servlet。一个Context有一个或多个Wrapper,而Wrapper 作为容器层次中的最底层,不能包含子容器。

 

Tomcat文件目录对照:

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 采用责任链模式,即一个请求处理的过程中有很多处理者依次对请求进行相应处理,一个处理完之后将处理后的请求返回,下一个处理继续。

 

Tomcat.基础.架构

 

Pipeline-Valve 使用的责任链模式的特点:

  1. 每个 Pipeline 都有特定的 Valve,而且是在管道的最后一个执行,这个Valve 叫做BaseValve,BaseValve 是不可删除的。
  2. 在上层容器的管道的 BaseValve 中会调用下层容器的管道。

 

Pipeline的处理流程图如下:

Tomcat.基础.架构

 

Container 包含的四个子容器对应的 BaseValve 分别在:

StandardEngineValve、StandardHostValve、StandardContextValve、StandardWrapperValve。

 

  1. Connector 在接收到请求后会首先调用 EnginePipeline,在 Engine 的管道中依次执行,按箭头指向最后执行到 WrapperPipeline 的 StandardWrapperValve。
  2. 最后在StandardWrapperValve 中创建 FilterChain,这个 FilterChain 包含我们配置的与请求相匹配的 Filter 和 Servlet,其doFilter方法会依次调用所有Filter 的doFilter方法和Servlet 的 service 方法。
  3. 当所有的 Pipeline-Valve 都执行完之后就将返回的结果交给 Connector,Connector 再通过 Socket 的方式将结果返回给客户端。

 

至此,我们已经对Tomcat的基本架构有了大致的了解