Tomcat 学习笔记

核心架构

  1. Tomcat 核心配置 server.xml 树形结构:
<Server port="8005" shutdown="SHUTDOWN"> // 顶层组件,可包含多个 Service,代表一个 Tomcat 实例

  <Service name="Catalina">  // 顶层组件,包含一个 Engine ,多个连接器
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />

    
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />  // 连接器

    // 容器组件:一个 Engine 处理 Service 所有请求,包含多个 Host
    <Engine name="Catalina" defaultHost="localhost">
      // 容器组件:处理指定Host下的客户端请求, 可包含多个 Context
      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">
            // 容器组件:处理特定 Context Web应用的所有客户端请求
            <Context>Context>
      Host>
    Engine>
    
  Service>
Server>
  1. 架构
    Tomcat 学习笔记_第1张图片
  • Connector 负责通信
  1. 监听网络端口;
  2. 读取网络字节流;
  3. 将网络字节流封装成 request 对象;
  4. 调用 servlet 容器,获取 response 对象;
  5. 将 response 对象序列化成字节流,并返回给浏览器。
  • Engine 负责请求处理
    • host 是虚拟主机,与请求域名相绑定
    • 每个 Context 对应一个 JavaWeb 应用

其它

  1. Tomcat 架构原理解析到架构设计借鉴

通过抽象「应用层通信协议」和 「网络通信细节」为 Request、Response,使程序员专注于业务。

Tomcat 实现的 2 个核心功能:

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

分别对应了 Tomcat 的两个核心组件连接器(Connector)和容器(Container),连接器负责对外交流,容器负责内部逻辑处理。Tomcat为支持多种 I/O 模型(NIO、NIO2、APR)和应用层协议(HTTP/1.1、HTTP2、AJR),一个容器可对接多个连接器,就好比一个房间有多个门。连接器对 Servlet 容器屏蔽了网络协议与 I/O 模型的区别,无论是 Http 还是 AJP,在容器中获取到的都是一个标准的 ServletRequest 对象。

Tomcat 学习笔记_第2张图片
EndPoint 接收到 Socket 连接后,生成一个 SocketProcessor 任务提交到线程池去处理,SocketProcessor 的 Run 方法会调用 HttpProcessor 组件去解析应用层协议,Processor 通过解析生成 Request 对象后,会调用 Adapter 的 Service 方法,方法内部通过 以下代码将请求传递到容器中:connector.getService().getContainer().getPipeline().getFirst().invoke(request, response); // CoyoteAdapter 触发 Pipeline-Valve 责任链执行


Tomcat 学习笔记_第3张图片
Servlet 容器顾名思义就是用来保存 Servlet 的容器,为了使容器有更好的灵活性,Tomcat 使用了分层架构的思想,设计出了 4 种容器,分别是 Engine、Host、Context和 Wrapper(四种容器属于父子关系)。
Tomcat 学习笔记_第4张图片
Wrapper 表示一个 Servlet ,Context 表示一个 Web 应用程序,而一个 Web 程序可能有多个 Servlet ;Host 表示一个虚拟主机,或者说一个站点,一个 Tomcat 可以配置多个站点(Host);一个站点( Host) 可以部署多个 Web 应用;Engine 代表引擎,用于管理多个站点(Host),一个 Service 只能有 一个 Engine。

Tomcat 使用组合模式来管理这些容器。具体实现方法是,所有容器组件都实现了 Container 接口,因此组合模式可以使得用户对单容器对象和组合容器对象的使用具有一致性。这里单容器对象指的是最底层的 Wrapper,组合容器对象指的是上面的 Context、Host 或者 Engine。Container 接口又继承了 LifeCycle 接口(主要包含:init()、start()、stop() 和 destroy()),使得 Tomcat 可以对这些容器组件进行统一生命周期管理。在父组件的 init() 方法里需要创建子组件并调用子组件的 init() 方法。同样,在父组件的 start() 方法里也需要调用子组件的 start() 方法,因此调用者可以无差别地调用各组件的 init() 方法和 start() 方法。Tomcat 只要调用最顶层组件,也就是 Server 组件的 init() 和start() 方法,整个服务器就被启动起来了。

Tomcat 学习笔记_第5张图片
连接器中的 Adapter 会调用容器的 Service 方法来执行 Servlet,最先拿到请求的是 Engine 容器,Engine 容器对请求做一些处理后,会把请求传给自己子容器 Host 继续处理,依次类推,最后这个请求会传给 Wrapper 容器,Wrapper 会调用最终的 Servlet 来处理。那么这个调用过程具体是怎么实现的呢?答案是使用 Pipeline-Valve 管道。

Pipeline-Valve 是责任链模式,责任链模式是指在一个请求处理的过程中有很多处理者依次对请求进行处理,每个处理者负责做自己相应的处理,处理完之后将再调用下一个处理者继续处理。Pipeline 中维护了 Valve 链表,Valve 表示一个处理点。整个调用链的触发是 Valve 来完成的,Valve完成自己的处理后,调用 getNext.invoke() 来触发下一个 Valve 调用。
Tomcat 学习笔记_第6张图片
每个容器都有一个 Pipeline 对象,只要触发了这个 Pipeline 的第一个 Valve,该 Pipeline 中的其它 Valve 就都会被调用到。但是,不同容器的 Pipeline 是怎么链式触发的呢,比如 Engine 中 Pipeline 需要调用下层容器 Host 中的 Pipeline。这是因为 Pipeline 中还有个 getBasic 方法。这个 BasicValve 处于 Valve 链表的末端,它是 Pipeline 中必不可少的一个 Valve,负责调用下层容器的 Pipeline 里的第一个 Valve。Wrapper 容器的最后一个 Valve 会创建一个 Filter 链,并调用 doFilter() 方法,最终会调到 Servlet 的 service 方法。

Valve 和 Servlet Filter 的区别是:

  1. Valve是 Tomcat 的私有机制,与 Tomcat 的基础架构 API 是紧耦合的,而 Servlet API 是公有的标准,所有的 Web 容器包括 Jetty 都支持 Filter 机制。
  2. Valve 工作在 Web 容器级别,会拦截所有应用的请求;而 Servlet Filter 工作在应用级别,只能拦截某个 Web 应用的所有请求。如果想做整个 Web 容器的拦截器,必须通过 Valve 来实现。

  1. 万字详解 Tomcat 组成与工作原理
  2. 经典书籍:深入剖析Tomcat
  3. Apache Tomcat 8 Configuration Reference

你可能感兴趣的:(tomcat,tomcat)