Tomcat有两个核心功能:

  1. 处理 Socket 连接,负责网络字节流与 Request 和 Response 对象的转化。
  2. 加载和管理 Servlet,以及具体处理 Request 请求。

Tomcat 设计了两个核心组件连接器(Connector)和容器(Container)来分别做这两件事情。

连接器负责对外交流,容器负责内部处理。

最顶层是 Server 服务器,这里的 Server 指的就是一个 Tomcat 实例。一个 Server 中有一个或者多个 Service,一个 Service 中有多个连接器和一个容器。连接器与容器之间通过标准的 ServletRequest 和 ServletResponse 通信。

  • catalina 是Tomcat服务器使用Servlet容器的名字。 
  • 我们可以把catalina看成是两个主要模块组成的,连接器(connector)和容器(container)。

Tomcat的连接器和容器简介

  • 连接器是用来“连接”容器里边的请求的。它的工作是为接收到每一个HTTP请求构造一个request和response对象。然后它把流程传递给容器。容器从连接器接收到requset和response对象之后调用servlet的service方法用于响应。
  • Connector连接器的主要功能,是接收连接请求,创建Request和Response对象用于和请求端交换数据;然后分配线程让Engine(也就是Servlet容器)来处理这个请求,并把产生的Request和Response对象传给Engine。当Engine处理完请求后,也会通过Connector将响应返回给客户端。
  • Servlet容器处理请求,是需要Connector进行调度和控制的,Connector 是Tomcat 处理请求的主干 
  • 无论是BIO,还是NIO,Connector处理请求的大致流程是一样的:
  • 在accept 队列中接收连接(当客户端向服务器发送请求时,如果客户端与OS 完成三次握手建立了连接,则OS 将该连接放入accept 队列);在连接中获取请求的数据,生成request ;调用servlet 容器处理请求;返回response 
  • 连接是TCP层面的(传输层),对应socket;请求是HTTP层面的(应用层),必须依赖于TCP的连接实现;一个TCP连接中可能传输多个HTTP请求。

连接器的工作流程可分为:

  • 监听网络端口。
  • 接受网络连接请求。
  • 读取请求网络字节流。
  • 根据具体应用层协议(HTTP/AJP)解析字节流,生成统一的 Tomcat Request 对象。
  • 将 Tomcat Request 对象转成标准的 ServletRequest。
  • 调用 Servlet 容器,得到 ServletResponse。
  • 将 Tomcat Response 转成网络字节流。
  • 将响应字节流写回给浏览器。

Tomcat 是用 Mapper 组件来完成确定请求是由哪个 Wrapper 容器里的 Servlet 来处理的。

Mapper 组件的功能就是将用户请求的 URL 定位到一个 Servlet,它的工作原理是: Mapper 组件里保存了 Web 应用的配置信息,其实就是容器组件与访问路径的映射关系, 比如 Host 容器里配置的域名、Context 容器里的 Web 应用路径,以及 Wrapper 容器里 Servlet 映射的路径,这些配置信息就是一个多层次的 Map。

当一个请求到来时,Mapper 组件通过解析请求 URL 里的域名和路径,再到自己保存的 Map 里去查找,就能定位到一个 Servlet。一个请求 URL 最后只会定位到一个 Wrapper 容器,也就是一个 Servlet。

假如有用户访问一个 URL,比如图中的 http://user.shopping.com:8080/order/buy,Tomcat 如何将这个 URL 定位到一 个 Servlet 呢? 首先,根据协议和端口号选定 Service 和 Engine。我们知道 Tomcat 的每个连接器都监听不同的端口,比如 Tomcat 默认的 HTTP 连接器监 听 8080 端口、默认的 AJP 连接器监听 8009 端口。上面例子中的 URL 访问的是 8080 端 口,因此这个请求会被 HTTP 连接器接收,而一个连接器是属于一个 Service 组件的,这 样 Service 组件就确定了。我们还知道一个 Service 组件里除了有多个连接器,还有一个容 器组件,具体来说就是一个 Engine 容器,因此 Service 确定了也就意味着 Engine 也确定 了。然后,根据域名选定 Host。Service 和 Engine 确定后,Mapper 组件通过 URL 中的域名去查找相应的 Host 容器,比 如例子中的 URL 访问的域名是user.shopping.com,因此 Mapper 会找到 Host2 这个 容器。之后,根据 URL 路径找到 Context 组件。 Host 确定以后,Mapper 根据 URL 的路径来匹配相应的 Web 应用的路径,比如例子中访 问的是 /order,因此找到了 Context4 这个 Context 容器。 最后,根据 URL 路径找到 Wrapper(Servlet)。Context 确定后,Mapper 再根据 web.xml 中配置的 Servlet 映射路径来找到具体的 Wrapper 和 Servlet。

连接器中的Adapter 会调用容器的 Service 方法来执行 Servlet,最先拿到请求的是 Engine 容器, Engine 容器对请求做一些处理后,会把请求传给自己子容器 Host 继续处理,依次类推, 最后这个请求会传给 Wrapper 容器,Wrapper 会调用最终的 Servlet 来处理。

相关文章: