Tomcat最底层使用的是Java标准的SocketServer和Socket接受和处理请求,但是Socket接受到的数据是网络运输层的TCP或UDP协议的数据,需要转为Http或者其它应用层协议的数据。Tomcat中就是通过连接器Connector来管理Socket连接、解析Scoket请求为Request并封装响应数据为Response对象。新版本的Tomcat容器使用的连接器是Coyote框架,本文会详细介绍Connector的Coyote框架原理。本文很多内容参考了这篇博客

什么是Coyote

Coyote是Tomcat链接器框架的名称,是Tomcat服务器提供的供客户端访问的外部接口。客户端通过Coyote与服务器建立链接、发送请求并且接收响应。

Coyote封装了底层的网络通信(Socket请求以及响应处理),为Catalina容器提供了统一的接口,是Catalina容器与具体的请求协议以及 I/O方式解耦。Coyote将Socket输入转换为Request对象,交由Catalina容器进行处理,处理请求完成之后,Catalina通过Coyote提供的Response对象将结果写入输出流。

Coyote作为独立的模块,只负责具体协议和I/O的处理,与Servlet规范实现没有直接关系,因此即便是Request和Response对象也并未实现Servlet规范对应的接口,而是在Catalina中将他们进一步封装为ServletRequest何ServletResponse。

Coyote支持的协议

Coyote框架支持以下三种应用层协议:

  1. HTTP/1.1协议:这是绝大多数Web应用采用的访问协议,主要用于Tomcat单独运行(不予Web服务器集成)的情况。
  2. AJP协议:用于和Web服务器(如Apache HTTP Server)集成,以实现针对静态资源的优化以及集群部署,当前支持AJP/1.3。
  3. HTTP/2.0协议:下一代HTTP协议,自Tomcat8.5以及9.0版本开始支持,截止目前,主流的最新版本均已支持HTTP/2.0。

针对HTTP和AJP协议,Coyote又按照 I/O方式分别提供了不同的选择方案(自8.5/9.0版本起,Tomcat已出了对BIO的支持)。

  1. NIO:采用Java NIO类库实现。
  2. NIO2:采用JDK 7最新的NIO2类库实现。
  3. APR:采用APR(Apache可移植运行库)实现

在8.0之前,Tomcat默认采用的I/O方式为BIO,之后采用NIO。无论NIO、NIO2还是APR,在性能方面均优于以往的BIO。如果采用APR,甚至可以达到接近于 Apache HTTP Server的响应性能。

在Coyote中,HTTP/2.0的处理方式与HTTP/1.1和AJP不同,采用一种升级协议的方式实现,这也是有HTTP/2.0的传输方案决定的。

可以采用一种简单的分层视图来描述Tomcat对协议以及 I/O方式的支持,如下图所示:

Connector的核心概念

在Connector中有如下几个核心概念:

  • Endpoint:Coyote通信端点,即通信监听的接口,是具体的Socker接收处理类,是对传输层的抽象。Tomcat并没有Endpoint接口,而是提供了一个抽象类AvstractEndpoint。根据I/O方式的不同,提供了NioEndpoint(NIO)、AprEndpoint(APR)以及Nio2Endpoint(NIO2)三个实现。
  • Processor:Coyote协议处理接口,负责构造Request和Response对象,并且通过Adapter将其提交到Catalina容器处理,是对应用层的抽象。Processor是单线程的,Tomcat在同一次链接中复用Processor。Tomcat按照协议的不同提供了3个实现类:Http11Processor(HTTP/1.1)、AjpProcessor(AJP)、StreamProcessor(HTTP/2.0)。除此之外,他还提供了两个用于处理内部处理的实现:UpgradeProcessorInternal和UpgradeProcessorExternal,前者用于处理内部支持的升级协议(如HTTP/2.0和WebSocket),后者用于处理外部扩展的升级协议支持。
  • UpgradeProtocol:Tomcat采用UpgradeProtocol接口表示HTTP升级协议,当前只提供了一个实现(Http2Protocol)用于处理HTTP/2.0.他根据请求创建一个用于升级处理的令牌UpgradeToken,该令牌中包含了具体的HTTP升级处理器HttpUpgradeHandler,HTTP/2.0的处理器实现为Http2UpgradeHandler。Tomcat中的WebSocket也是通过UpgradeToken机制实现的。

Connector请求处理流程

Connector处理请求的流程如上所示,我们一步步分析一下流程的内容:

  1. 当Connector启动时,会同时启动其持有的Endpoint实例。Endpoint并允许多个线程(有属性acceptorThreadCount确定),每个线程允许一个AbstractEndpoint.Acceptor实例。在AbstractEndpoint.Acceptor实例中监听端口通信(I/O方式不同,具体的处理方式也不同),而且只要Endpoint处于运行状态,始终循环监听。
  2. 当监听到请求时,Acceptor将Socker封装为SocketWrapper实例(此时并未读取数据),并交由一个SocketProcessor对象处理(此过程也由线程池异步处理)。此部分根据I/O方式的不同处理会有所不同,如NIO采用轮询的方式检测SelectionKey是否就绪。如果就绪,则获取一个有效的SocketProcessor对象并且提交线程池处理。
  3. SocketProcessor是一个线程池Worker实例,每一个I/O方式均有自己的实现。他首先判断Socket的状态(如完成SSL握手),然后提交到ConnectionHandler处理。
  4. ConnectionHandler是AbstractProtocol的一个内部类,主要用于链接选择一个合适的Processor实现以进行请求处理。
    • 提升性能,他针对每个有效的理解都会缓存器Processor对象。不仅如此,当前链接关闭时,其Processor对象还会被释放到一个回收队列(升级协议不会回收),这样后续链接可以重置并且重复利用,以减少对象构造。
    • 在处理请求时,他首先会从缓存中获取当前链接的Processor对象。如果不存在,则尝试根据协商协议构造Processor(如HTTP/2.0请求)。如果不存在协商协议(如HTTP/1.1请求),则从回收队列中获取一个已释放的Processor对象使用。如果回收队列中没有可用的对象,那么由具体的协议创建一个Processor使用(同时注册到缓存)。
  5. 协议升级时,ConnectionHandler会从当前Processor得到一个UpgradeToken对象(如果没有,则默认为HTTP/2),并构造一个升级Processor实例(如果是Tomcat支持的协议则会是UpgradeProcessorInternal,否则是UpgradeProcessorExternal)替换当前的Processor,并将当前的Processor释放回收。替换后,该链接的后续处理将由升级Process完成。
  6. 通过UpgradeToken中HttpUpgradehandler对象的init()方法进行初始化,以便准备开始启用新协议。

我是御狐神,欢迎大家关注我的微信公众号:wzm2zsd

本文最先发布至微信公众号,版权所有,禁止转载!

学习Tomcat(三)之容器连接器的更多相关文章

  1. Spring学习总结三——SpringIOC容器三

    一:spring容器自动装配注入 为了减少xml中配置内容,可以使用自动装配注入,代替setter注入,只需要在 bean对象配置中添加属性autoWire即可,那么在类中就会自动扫描setXXX() ...

  2. STL学习笔记(三) 关联容器

    条款19:理解相等(equality)和等价(equivalence)的区别 相等的概念是基于 operator== 的,如果 operator== 的实现不正确,会导致并不实际相等等价关系是以&qu ...

  3. tomcat(5)servlet容器

    [0]README 0.0)本文部分文字描写叙述转自:"深入剖析tomcat",旨在学习 tomcat(5)servlet容器 的基础知识. 0.1)intro to servle ...

  4. Tomcat剖析(三):连接器(2)

    Tomcat剖析(三):连接器(2) 1. Tomcat剖析(一):一个简单的Web服务器 2. Tomcat剖析(二):一个简单的Servlet服务器 3. Tomcat剖析(三):连接器(1) 4 ...

  5. Tomcat剖析(三):连接器(1)

    Tomcat剖析(三):连接器(1) 1. Tomcat剖析(一):一个简单的Web服务器 2. Tomcat剖析(二):一个简单的Servlet服务器 3. Tomcat剖析(三):连接器(1) 4 ...

  6. JavaWeb学习总结(三)——Tomcat服务器学习和使用(二) 包含https 非对称秘钥 NB

    JavaWeb学习总结(三)--Tomcat服务器学习和使用(二) 一.打包JavaWeb应用 在Java中,使用"jar"命令来对将JavaWeb应用打包成一个War包,jar命 ...

  7. 学习Tomcat(一)之容器概览

    Tomcat是Apache软件基金会的一个顶级项目,由Apache.Sun和其它一些公司及个人共同开发,是目前比较流行的Web服务器之一.Tomcat是一个开源的.小型的轻量级应用服务器,具有占用系统 ...

  8. JSP学习笔记(三):简单的Tomcat Web服务器

    注意:每次对Tomcat配置文件进行修改后,必须重启Tomcat 在E盘的DATA文件夹中创建TomcatDemo文件夹,并将Tomcat安装路径下的webapps/ROOT中的WEB-INF文件夹复 ...

  9. JavaWeb学习总结(三)——Tomcat服务器学习和使用

    收藏 JavaWeb学习总结(三)——Tomcat服务器学习和使用 http://www.cnblogs.com/xdp-gacl/p/3744053.html

随机推荐

  1. 常见的Web攻击手段,拿捏了!

    大家好,我是小菜. 一个希望能够成为 吹着牛X谈架构 的男人!如果你也想成为我想成为的人,不然点个关注做个伴,让小菜不再孤单! 本文主要介绍 互联网中常见的 Web 攻击手段 如有需要,可以参考 如有 ...

  2. Notes about multiboot usb creator

    U盘上的多系统启动工具,Windows上YUMI比较好,Ubuntu上MultiSystem用法复杂,unetbootin是另外一款,需要安装p7zip(apt-get install p7zip-f ...

  3. xml editing in vi

    Auto complete tags xmledit installation: git clone https://github.com/sukima/xmledit.git, then make ...

  4. 手工设置Eclipse文本编辑器的配色

    Eclipse中不同的文件都有自己专门的编辑器配色设置,下面分别说明. 文本编辑器的背景色: Window->Preferences-> General->Editors->T ...

  5. 51单片机—LCD1602显示模块

    文章目录 - 什么是LCD1602 - 如何操作LCD1602 - 上代码 - 什么是LCD1602 LCD:Liquid Crystal Display-液晶显示器,简称LCD,其主要显示原理是以电 ...

  6. 题解 [AHOI2017/HNOI2017]大佬

    传送门 注意到题面里n很小,有\(n\leq100\) 考虑联系n的实际意义 n是你在大佬手中能活的天数 题面颇富深意 好了不闹了 n很小,对于\(40\%\)的数据,爆搜即可 考场上靠这个骗了40p ...

  7. 黑马JVM教程——自学笔记(三)

    四.类加载与字节码技术 4.1.类文件结构 首先获得.class字节码文件 方法: 在文本文档里写入java代码(文件名与类名一致),将文件类型改为.java java终端中,执行javac X:.. ...

  8. (二)js基础。。。freecodecamp笔记

    个人需要注意的点 当 JavaScript 中的变量被声明的时候,程序内部会给它一个初始值undefined.当你对一个值为undefined的变量进行运算操作的时候,算出来的结果将会是NaN,NaN ...

  9. 设计模式<一>

    设计原则1.找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起. 2.针对接口编程,而不是针对实现编程. 3.多用组合,少用继承. 一:策略模式,定义了算法族,分别封装起来 ...

  10. Unable to instantiate org.apache.hadoop.hive.ql.metadata.SessionHiveMetaStoreClient

    1.今天在进行hive测试的时候,发现hive一直进不去,并且报了这个错误. Unable to instantiate org.apache.hadoop.hive.ql.metadata.Sess ...