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. Redis实战-详细配置-优雅的使用Redis注解/RedisTemplate

    1. 简介 当我们对redis的基本知识有一定的了解后,我们再通过实战的角度学习一下在SpringBoot环境下,如何优雅的使用redis. 我们通过使用SpringBoot内置的Redis注解(文章 ...

  2. Setup a Simple HTTP Proxy Server

    The host 10.21.3.69 has no H3C client, so it can't access the internet. With Tinyproxy, we can setuu ...

  3. MySQL学习02(操作数据库)

    操作数据库 结构化查询语句分类 名称 解释 命令 DDL(数据库定义语言) 定义和管理数据对象,例如数据库和数据表 create.drop.alter DML(数据操作语言) 用于操作数据库对象中所包 ...

  4. PostgreSQL 时间转换

    背景:最近频繁使用到时间转换相关的操作,特此小记. 1.实时取最近24小时内数据. select now() - interval '24h'; 通过sql获得符合要求的时间段,当做where条件即可 ...

  5. iOS开发之GIF转MP4

    前言 最近遇到需要将gif转化为mp4的问题,网上找的在线转换限制太多,索性就自己写了一个工具APP.文章末尾有开源代码和打包好的APP,如有需要请自行下载. 效果图 核心代码 来源 import I ...

  6. 【Vulnhub】DC-2靶机

    Vulnhub DC-2 靶机 信息搜集 访问web端发现访问不了,可以观察到相应的URL为域名而不是IP,需要在hosts文件种添加一条DNS记录. host位置:C:\Windows\System ...

  7. 解决uni-file-picker组件在ios点击失效的问题

    从组件源码里找到choose-and-upload-file.js文件,查找chooseAndUploadFile方法,在方法里添加下面代码,保存即可解决. opts.sourceType = ['a ...

  8. 使用C# 实现串口拨号器的SIM卡通信

    参考网址:https://www.cnblogs.com/xugang/archive/2012/08/23/2652671.html 写此博客意为抛砖引玉,希望能和博客园的朋友们探讨一下关于.NET ...

  9. .Net 生成带注释的Nuget包

    使用.NET Core时,我们的类库都要打包成nuget包上传到nuget服务器,以供自己或他人使用 .Net sdk提供了一个 .Net pack 命令可以生成nuget包.比如下面的命令 dotn ...

  10. 关于Ubuntu18.04 linux系统下使用Tim QQ 微信

    先配上张图 步骤: 1.1 :需要安装环境deepin-wine 1.1:(你把他理解为jdk就好,没有jdk无法运行java程序,同理没有deepin-wine环境无法运行腾讯产品) 1.2 :去哪 ...