深入拆解Tomcat & Jetty(二)

Tomcat要实现的2个核心功能

1、处理Socket连接,负责网络字节流与Request和Response对象的转化。

2、加载和管理Servlet,以及具体处理Request请求。

因此,Tomcat设计了两个核心组件连接器(Connector)和容器(Container)来分别做这两件事情。连接器负责HTTP Request和Response的转换,容器负责加载Servlet处理HTTP请求。

Tomcat连接器

用了三个核心组件:Endpoint、Processor和Adapter来分别做三件事情,其中Endpoint和Processor放在一起抽象成了ProtocolHandler组件。

ProtocolHandler组件:用来处理网络连接和应用层协议

Endpoint:是通信端点,即通信监听的接口,是具体Socket接收和发送处理器,是对传输层的抽象,因此Endpoint是用来实现TCP/IP协议的。

Processor:是用来实现HTTP协议的,Processor接收来自Endpoint的Socket,读取字节流解析成Tomcat Request和Response对象,并通过Adapter将其提交到容器处理,Processor是对应用层协议的抽象。

Adapter:Processor传来的是Tomcat Request对象,这个对象并不是标准的ServletRequest对象,所以连接器调用了CoyoteAdapter的service方法,传入的是Tomcat Request对象,CoyoteAdapter负责将Tomcat Request转化成ServletRequest,再调用容器的service方法。

连接器的组件图

 

从图中我们看到,Endpoint 接收到 Socket 连接后,生成一个 SocketProcessor 任务提交到线程池去处理, SocketProcessor 的 run 方法会调用 Processor 组件去解析应用层协议,Processor 通过解析生成 Request 对象后,会调用 Adapter 的 Service 方法。

容器的层次结构

1、请求过来时,根据协议和端口号确定连接器,也就确定了Service和Engine(容器);根据域名确认对应容器下哪个Host;根据URL路径找到Context;Context确定后再根据web.xml确实是哪个Servlet。这种分层架构是父子关系,不是平行关系,使得Servlet容器具有很好的灵活性。

2、你可以再通过 Tomcat 的server.xml配置文件来加深对 Tomcat 容器的理解。Tomcat 采用了组件化的设计,它的构成组件都是可配置的,其中最外层的是 Server,其他组件按照一定的格式要求配置在这个顶层容器中,如下图:

 

各层介绍

Engine 表示引擎,用来管理多个虚拟站点,一个 Service 最多只能有一个 Engine。

Host 代表的是一个虚拟主机,或者说一个站点,可以给 Tomcat 配置多个虚拟主机地址,而一个虚拟主机下可以部署多个 Web 应用程序。

Context 表示一个 Web 应用程序。

Wrapper 表示一个 Servlet,一个 Web 应用程序中可能会有多个 Servlet。

Tomcat如何管理这些容器的?

运用组合模式对这些容器进行管理。具体实现方法是:所有容器组件都实现了Container接口,因此组合模式可以使得用户对单容器对象(Wrapper/Servlet)组合容器对象(Context、Host 或者 Engine)的使用具有一致性。

Container接口定义如下图:

 如何实现定位Servlet请求的?

通过mapper实现逐级查询定位(key-value)

这个逐级调用过程如何实现的

Pipeline-Valve是责任链模式,责任链模式是指在一个请求处理的过程中有很多处理者依次对请求进行处理,每个处理者负责做自己相应的处理,处理完之后将再调用下一个处理者继续处理。

Valve 表示一个处理点。

 

 

// Calling the container
connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);

 Valve 和 Filter 有什么区别吗?

Valve是Tomcat的私有机制,与Tomcat的基础架构/API是紧耦合的。Servlet API是有公有的标准,所以的web容器包括Jetty都支持Filter机制

Valve工作在Web容器级别,拦截所有应用的请求;而Servlet Filter工作在应用级别,只能拦截某个Web应用的所有请求。

Tomcat中的Context组件跟Servlet规范中的ServletContext接口有什么区别?跟spring中的ApplicationContext又有什么关系?

(1)Servlet规范中ServletContext表示web应用的上下文环境,而web应用对应tomcat的概念是Context,所以从设计上,ServletContext自然会成为tomcat的Context具体实现的一个成员变量。

(2)tomcat内部实现也是这样完成的,ServletContext对应tomcat实现是org.apache.catalina.core.ApplicationContext,Context容器对应tomcat实现是org.apache.catalina.core.StandardContext。ApplicationContext是StandardContext的一个成员变量。

(3)Spring的ApplicationContext之前已经介绍过,tomcat启动过程中ContextLoaderListener会监听到容器初始化事件,它的contextInitialized方法中,Spring会初始化全局的Spring根容器ApplicationContext,初始化完毕后,Spring将其存储到ServletContext中。

(4)总之,Servlet规范中ServletContext是tomcat的Context实现的一个成员变量,而Spring的ApplicationContext是Servlet规范中ServletContext的一个属性。

Tomcat脚本启动后的内部流程

Tomcat 本质是 Java 程序, [startup.sh](http://startup.sh) 启动 JVM 运行 Tomcat 启动类 bootstrap;

Bootstrap 初始化类加载器, 创建 Catalina

Catalina 解析 server.xml, 创建相应组件, 调用 Server start 方法

Server 组件管理 Service 组件并调用其 start 方法

Service 负责管理连接器和顶层容器 Engine, 其会调用 Engine start 方法

这些类不处理具体请求, 主要管理下层组件, 并分配请求

Catalina 完成两个功能:(1)解析 server.xml, 创建定义的各组件, 调用 server init 和 start 方法;(2)处理异常情况, 例如 ctrl + c 关闭 Tomcat. 其会在 JVM 中注册"关闭钩子"--关闭钩子, 在关闭 JVM 时做清理工作, 例如刷新缓存到磁盘,关闭钩子是一个线程, JVM 停止前会执行器 run 方法, 该 run 方法调用 server stop 方法

Server 组件, 实现类 StandServer
    - 继承了 LifeCycleBase
    - 子组件是 Service, 需要管理其生命周期(调用其 LifeCycle 的方法), 用数组保存多个 Service 组件,

动态扩容数组来添加组件
    - 启动一个 socket Listen停止端口, Catalina 启动时, 调用 Server await 方法, 其创建 socket Listen 8005 端口, 并在死循环中等连接, 检查到 shutdown 命令, 调用 stop 方法

Service 组件, 实现类 StandService
    - 包含 Server, Connector, Engine 和 Mapper 组件的成员变量
    - 还包含 MapperListener 成员变量, 以支持热部署, 其Listen容器变化, 并更新 Mapper, 是观察者模式

Engine 组件, 实现类 StandEngine 继承 ContainerBase
    - ContainerBase 实现了维护子组件的逻辑, 用 HaspMap 保存子组件, 因此各层容器可重用逻辑
    - ContainerBase 用专门线程池启动子容器, 并负责子组件启动/停止, "增删改查"
    - 请求到达 Engine 之前, Mapper 通过 URL 定位了容器, 并存入 Request 中. Engine 从 Request 取出 Host 子容器, 并调用其 pipeline 的第一个 valve

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值