类图

Tomcat整体架构

组件关系

Tomcat整体架构

启动流程

Tomcat有三种启动方式

  • From the command line
  • From a Java program as an embedded server
  • Automatically as a Windows service
Bootstrap初始化
  1. 设置类加载器

    • commonLoader (common)-> System Loader
    • sharedLoader (shared)-> commonLoader -> System Loader
    • catalinaLoader(server) -> commonLoader -> System Loader
    • 默认情况下,commonLoader用于sharedLoader和serverLoader
  2. 通过反射加载启动类

    • org.apache.catalina.startup.Catalina
    • setParentClassloader-> sharedLoader
    • Thread.contextClassloader-> catalinaLoader
  3. 完成Bootstrap.daemon.init(),即完成初始化

输入命令行参数

假设命令为start

  1. Catalina.setAwait(true)阻塞当前daemon

  2. Catalina.load()

    • initDirs()
  • initNaming()
    • createStartDigester()
  • 加载server.xml并使用Digester对其解析
    • 将System.out和System.err分配给SystemLogHandler类
  • 在所有组件上调用初始化,这使每个对象向JMX代理。在调用过程中,连接器还会初始化适配器(它是执行请求预处理的组件)。默认的适配器协议是Http1.1
  1. Catalina.start()

    • 启动NamingContext并将所有JNDI引用绑定到其中

    • 启动Server下的services:
      StandardServicestartsEngine(ContainerBaseRealm,Cluster,etc) StandardService\rightarrow starts Engine(ContainerBase\rightarrow Realm, Cluster,etc)

    • 在容器(StandardEngine)的生存期内,有一个后台线程继续检查上下文是否已更改。如果上下文发生变化(war,xml的时间戳),然后重新加载(停止/删除/部署/启动)

请求过程

Coyote负责Connector模块,Calatina负责容器模块

  1. 该请求由正在ThreadPoolExecutor类中等待的单独线程接收
  2. ThreadPoolExecutor分配一个TaskThread来处理请求。还会向Catalina容器提供JMX对象名
  3. 一般情况下,会调用Coyote Http11Processor进行协议解析,并通过Processor读取数据。这个Processor还将继续检查socket的inputStream直到到达保持活动点或连接断开
    • 在调永Http11Processor解析Http请求的过程中,会通过缓冲区类Http11InputBuffer解析请求行,端口等相关协议内容
  4. Processor中包含对CoyoteAdapter的引用。当Http11Processor解析完请求之后,会调用其引用的Adapter的service(request, response)方法。该方法负责唤醒所有的监听器。同时通过Mapper解析所有内容并将其与request,cookie,context进行关联
  5. 之后,CoyoteAdapter通过connector.getService().getContainer()调用容器StandardEngine,并且调用其getPipeline().getFirst().invoke(request,response)方法从Engine级别启动HTTP请求到Catalina容器 (getFirst的返回值是Valve)
    • 从这里可以看出每次调用都借助了责任链模式
    • 默认的Engine只有一个Valve,即StandardEngineValve,即通过该valve的invoke去调用StandardEngine
  6. tandardEngineValve.invoke()中会再次通过host.getPipeline().getFirst().invoke(request, response);去调用Host类的管道去唤醒Host容器
    • StandardHost有两个默认valve,即StandardHostValve和ErrorrEportValve
    • StandardHostValve会关联当前线程的类加载器,同时也会检索与请求关联的Manager和Session,如果Session存在,则保持会话状态
  7. 之后StandardHostValve.invoke()会再次通过context.getPipeline().getFirst().invoke(request, response);唤醒在与request关联的context上的pipeline
    • 先唤醒FormAuthenticao这个Valve,再唤醒StandardContextValve
    • StandardContextValve调用与context关联的所有ContextListener
  8. 接下来,通过wrapper.getPipeline().getFirst().invoke(request, response);唤醒Wrapper组件(StandardWrapperValve)中的pipeline
    • 在这个过程中,调用Jsp Wrapper(Jasper),实际编译JSP,然后调用实际的Servlet
      Tomcat整体架构

参考资料

相关文章: