写点什么

Tomcat 架构的认知

用户头像
邱学喆
关注
发布于: 2021 年 06 月 16 日
Tomcat架构的认知

一. 概述

下面是有关 tomcat 的架构图,这里不过里面的细节进行解读;只关注一个请求是怎么流转到 Servlet 进行大概的梳理;同时,我们是基于 spring-boot 框架中包含的 tomcat 源码进行解读;

二. 时序图

一个 Web 服务器,首先需要有一个监听线程。当请求过来,该线程就会接收到一个 socket 对象,然后交由 Processor 接口对应的实现类去解析,将解析后的请求数据,扔给 CoyoteAdapter 对象接着。如下图;这里没有忽略了很多细节,如 IO 多路复用的逻辑等;

上图还没涉及到 Service、Engine、Host、Context、Wrapper 相关的类;只是简单的画到 CoyoteAdapter 对象,其实际后面还有很长的链路;为了更加可观,我将其拆分出来;


通过上面的三张时序图,我们大体清楚地一个请求是如何流转到 Servlet 实现类的;

三. 关键问题解读

tomcat 包含的细节过多,如果去梳理里面的细节,会陷入死循环。所以我们带着问题去解读关键的代码逻辑;

1. 请求 URL 映射 Servlet

当一个请求过来的,我们会解析该 URL,找到对应的 Servlet 对象,然后封装到 StandardWrapper 中保存到 Request 对象中;接着通过 PipeLine 执行,最终到 StandardWrapperValve 时,获取 Request 中的 Wrapper 对象。接着就运行如上第三张时序图的流程;

具体映射的逻辑在 CoyoteAdapter 类;其通过 Service 对象的 Mapper 对象去映射逻辑,具体是调用如下方法:

//Mapperpublic void map(MessageBytes host, MessageBytes uri, String version,MappingData mappingData)
复制代码

2. session 管理

会话对象默认的实现类是 StandardSession,其会话管理接口是 Manager,默认的实现类为 StandardManager,该类是基于内存式管理会话对象;

那么问题来了,如何实现会话共享呢?

其实质是需要我们实现该 Manager 接口,然后注入到 tomcat 容器里面;至于如何注入?

  • 一种形式是通过 context.xml,去修改,该方式算是过时的;

在 spring boot 中,提供这样子的接口 TomcatContextCustomizer,可以让我们去自定义这个上下文 Context,代码处:

//TomcatServletWebServerFactoryprotected void configureContext(Context context,ServletContextInitializer[] initializers)
复制代码

3. 添加 Servlet/Filter

在 tomcat 中提供这样子的注解 @WebServlet,@WebFilter;然后并没有提供扫描 classpath 下的含有该注解的类向 Context 注入 Servlet;而在 spring-boot 框架中提供了这么一个类 ServletComponentScanRegistrar 可以扫描指定路径下的含有这些注解的对象向容器中注入,我们可以使用 @ServletComponentScan 去指定路径;


4. ServletContainerInitializer

tomcat 中提供了这个 ServletContainerInitializer 接口,可以对 Context 进行配置;在 spring-boot 框架中提供了主要的实现类为 TomcatStarter 类,然而 TomcatStarter 类中包含了 ServletContextInitializer 集合列表,可以对 ServletContext 进行初始化;有关 ServletContextInitializer 实现类有如下:

  • SessionConfiguringInitializer 对 Session 进行配置初始化

  • ServletListenerRegistrationBean 向 Servlet 容器中注册监听器;

  • ServletRegistrationBean 向 Servlet 容器中注册 Servlet

  • FilterRegistrationBean 向 Servlet 容器中注册 Filter

四. 总结

这里对 tomcat 的原理细节没有过多讲解,通过上面的几个点梳理,当在开发过程中需要基于 tomcat 下进行拓展的场景下,可以快速找到对应的代码处;后面会逐步完善该文章,另外值得推荐的是一本书:《Tomcat 内核设计剖析》,作者汪建

发布于: 2021 年 06 月 16 日阅读数: 14
用户头像

邱学喆

关注

计算机原理的深度解读,源码分析。 2018.08.26 加入

在IT领域keep Learning。要知其然,也要知其所以然。原理的爱好,源码的阅读。输出我对原理以及源码解读的理解。个人的仓库:https://gitee.com/Michael_Chan

评论 (2 条评论)

发布
用户头像
提问: 限流器该怎么实现?
2021 年 06 月 17 日 20:38
回复
在AbstractEndpoint对象中LimitLatch属性,其实质是AQS机制,最大能接受到的请求量;默认值是10000;我们可以通过ServerProperties对象中的Tomcat对象中maxConnections进行修改;
2021 年 06 月 17 日 20:47
回复
没有更多了
Tomcat架构的认知