Tomcat-启动流程和http请求流程


​ 分析并总结了tomcat的启动流程和整个http请求流程,重点可关注启动流程的UML图和请求流程图

启动流程

通过前面几篇的铺垫,现在终于可以进入到tomcat的启动流程了

  1. 架构和Lifecycle
  2. Server,Service,Conncector,ProtocolHandler和NioEndpoint
  3. Engine,Host和HostConfig
  4. Context,ContextConfig和Wrapper

​ Tomcat 的启动通常通过执行 catalina.sh start 命令完成。通过如下脚本可知是调用 org.apache.catalina.startup.Bootstrap#main(String[] args) 方法,并传入了 start 参数。

tomcat中catalina.sh脚本启动

Bootstrap#main

tomcat-startup-uml.png

启动流程UML

Bootstrap 初始化

​ 主要是初始化三个类加载器(Common、Catalina、Shared),并实例化Catalina对象,为后续的load和start方法做准备

Catalina#load()

​ 解析 conf/server.xml 配置文件,构建出一个Server树,并初始化Server(Server#init

Catalina#start()

​ 启动Server组件(Server#start

重点

  1. 容器的init() 并不会向子容器递归传播

    ​ 除了 Engine 容器在 load() 阶段被显式初始化外,其余子容器(如 HostContextWrapper)的初始化会延迟到 start() 阶段。也就是说,start() 阶段才是触发完整容器结构构建的关键时机

  2. Socket 层组件的启动滞后于容器启动

    ​ 只有整个容器启动完毕,确保业务逻辑准备完毕,然后才启动 Connector 及其内部的 ProtocolHandlerEndpoint(负责监听端口与处理 Socket 请求)。避免http请求到来时,容器还不可用的状态

  3. Context 容器由 HostConfig 解析生成

    ​ Host 启动时会触发其绑定的 LifecycleListener — HostConfig,来解析和构造StandardContext子容器

  4. Wrapper、Filter、Listener 由 ContextConfig 解析构建

    ​ Context启动中会触其绑定的 LifecycleListener — ContextConfig,来进行全部的web.xml解析,完成对 Wrapper(即 Servlet)、Filter、Listener 等组件的构建与注册

请求流程

tomcat-request-handle.png

流程总结

  1. Acceptor线程(监听并接受连接)

    1. Acceptor线程监听到8080端口产生的连接,将其构造为PollerEvent提交到Poller 的事件队列中
  2. Poller线程(事件注册和监听)

    1. 轮询处理事件队列,将 PollerEvent 注册到 Java NIO 的 Selector 中,监听 OP_READ 事件
    2. 当某个 channel 上有数据可读时,构造一个 SocketProcessor 实例,并提交给后端的 worker 线程池执行。
  3. Worker线程(处理Socket请求)

    1. SocketProcessor#doRun:进行tcp握手处理
    2. ConnectionHandler#process:从 Processor 缓存池中获取或新建协议处理器(如 Http11Processor),并交由其处理请求
    3. AbstractProcessorLight#process:对不同的socket状态进行分发和处理(SocketEvent.OPEN_READ则走到Http11Processor#service)
    4. Http11Processor#service:通过Http11InputBuffer解析http请求,构造成Request和Response。并分发给CoyoteAdapter#service
    5. CoyoteAdapter#service通过Mapper组件将请求 URL 映射到对应的 HostContextWrapper并缓存,再调用顶层容器(Engine)的 Pipeline,正式进入容器级别的处理逻辑。
    6. 请求通过容器中内部Pipeline里的Valve,从basic Valve流出再流向下一层容器中的first Valve:StandardEngineValve -> StandardHostValve -> StandardContextValve -> StandardWrapperValve
    7. 最后一个阀门StandardWrapperValve:先进行Servlet的分配,再构造ApplicationFilterChain(过滤出对当前url能使用的Filter),依次调用 doFilter() 进行链式处理,全部通过后最终便走到Servlet#service中

重点

  1. Tomcat 使用 责任链(Pipeline + Valve) 模式处理请求流转,清晰解耦了容器级别的处理职责
  2. Processor 实例在请求结束后可被复用,避免重复构造,提升性能
  3. NIO + 多线程池模型实现高并发处理,前端是少量 Acceptor/Poller 线程,后端是灵活扩展的 Worker 线程池。

worker线程栈示例

http请求栈