深入拆解 Tomcat & Jetty
李号双
eBay 技术主管
38890 人已学习
新⼈⾸单¥68
登录后,你可以任选4讲全文学习
课程目录
已完结/共 45 讲
开篇词 (1讲)
深入拆解 Tomcat & Jetty
15
15
1.0x
00:00/00:00
登录|注册

05 | Tomcat系统架构(上): 连接器是如何设计的?

转换Tomcat Request为ServletRequest
适配器模式的应用
调用Adapter的Service方法
生成Request和Response对象
解析Socket请求
实现HTTP协议
包含Acceptor和SocketProcessor
实现TCP/IP协议
具体的Socket接收和发送处理器
通信端点
Adapter
Processor
Endpoint
Request/Response与ServletRequest/ServletResponse转化
应用层协议解析
网络通信
高内聚、低耦合原则
将响应字节流写回给浏览器
将Response对象转换为网络字节流
转换ServletResponse为Tomcat Response对象
调用Servlet容器处理请求
转换Request对象为ServletRequest
解析字节流生成Tomcat Request对象
读取网络请求字节流
接受网络连接请求
监听网络端口
HTTP/2
AJP
HTTP/1.1
APR
NIO.2
NIO
容器负责内部处理
连接器负责对外交流
让子类实现抽象方法
定义模板方法
使用接口和抽象基类封装不变点
找出变化点和不变点
确定子模块
分析需求
CoyoteAdapter
Processor
Endpoint
核心组件
子模块设计
功能需求
应用层协议
I/O模型
连接器和容器
设计思路
Adapter组件
ProtocolHandler组件
连接器
Tomcat支持的多种I/O模型和应用层协议
Tomcat总体架构
Tomcat连接器设计思路

该思维导图由 AI 生成,仅供参考

在面试时我们可能经常被问到:你做的 XX 项目的架构是如何设计的,请讲一下实现的思路。对于面试官来说,可以通过你对复杂系统设计的理解,了解你的技术水平以及处理复杂问题的思路。
今天咱们就来一步一步分析 Tomcat 的设计思路,看看 Tomcat 的设计者们当时是怎么回答这个问题的。一方面我们可以学到 Tomcat 的总体架构,学会从宏观上怎么去设计一个复杂系统,怎么设计顶层模块,以及模块之间的关系;另一方面也为我们深入学习 Tomcat 的工作原理打下基础。

Tomcat 总体架构

我们知道如果要设计一个系统,首先是要了解需求。通过专栏前面的文章,我们已经了解了 Tomcat 要实现 2 个核心功能:
处理 Socket 连接,负责网络字节流与 Request 和 Response 对象的转化。
加载和管理 Servlet,以及具体处理 Request 请求。
因此 Tomcat 设计了两个核心组件连接器(Connector)和容器(Container)来分别做这两件事情。连接器负责对外交流,容器负责内部处理。
所以连接器和容器可以说是 Tomcat 架构里最重要的两部分,需要你花些精力理解清楚。这两部分内容我会分成两期,今天我来分析连接器是如何设计的,下一期我会介绍容器的设计。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

Tomcat连接器设计复杂,通过连接器和容器实现Socket连接和Servlet管理功能。支持多种I/O模型和应用层协议,如NIO、APR、HTTP/1.1、AJP和HTTP/2。连接器模块包括Endpoint、Processor和Adapter,实现网络通信、协议解析和Request/Response处理。通过抽象接口和模块化设计,实现高内聚、低耦合,封装变化,增加复用性。连接器的组件图清晰展示了继承和层次关系。整体设计体现了Tomcat连接器的灵活性和扩展性,为深入学习Tomcat工作原理提供基础。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《深入拆解 Tomcat & Jetty 》
新⼈⾸单¥68
立即购买
登录 后留言

全部留言(124)

  • 最新
  • 精选
  • 电光火石
    对Tomcat的结构有个清晰的了解,其中有两个问题: 1. PorotocolHandler的继承关系是不是太重了,看起来像典型的多维度扩展,nio2在apj和1HTTP11都要做一遍,用组合会不会更好 2. 为什么要多一层adapter,在processor直接转换为容器的servletrequest和servletresponse不是更好,为什么要先转化Tomcat的request和response,再用adapter做一层转换消耗性能? 谢谢了!

    作者回复: 1,说的对,能用组合就不用继承,这里我感觉Tomcat设计者考虑的是通过多层继承来尽量重用一些通用的逻辑。另外I/O模型和应用层协议的个数也是可控的,用户可以在server.xml中直接指定想要的连接器类型:比如Http11NioProtocol和Http11Nio2Protocol。 2,这里的考虑是,如果连接器直接创建ServletRequest和ServletResponse对象的话,就和Servlet协议耦合了,设计者认为连接器尽量保持独立性,它不一定要跟Servlet容器工作的。另外对象转化的性能消耗还是比较少的,Tomcat对HTTP请求体采取了延迟解析的策略,也就是说,TomcatRequest对象转化成ServletRequest的时候,请求体的内容都还没读取呢,直到容器处理这个请求的时候才读取的。

    2019-05-21
    8
    166
  • 两个问题请教一下老师 第一,如何debug源码呢? 第二,tomcat和netty有什么区别呢?为什么netty常常用做底层通讯模块,而tomcat作为web容器呢?

    作者回复: 1)软件系统本质是对信息的处理,要跟踪信息在流动过程中的经过的关键环节,并在这些地方下断点,看看变量的值是什么。比如你可以在业务代码中下个断点,看看调用栈,看Tomcat和Spring是怎么调到你的代码的,然后在这个调用栈中的关键函数里上下都看看,先熟悉个大概,然后带着问题去深入调试。 2)你可以把Netty理解成Tomcat中的连接器,它们都负责网络通信,都利用了Java NIO非阻塞特性。但Netty素以高性能高并发著称,为什么Tomcat不把连接器替换成Netty呢?第一个原因是Tomcat的连接器性能已经足够好了,同样是Java NIO编程,套路都差不多。第二个原因是Tomcat做为Web容器,需要考虑到Servlet规范,Servlet规范规定了对HTTP Body的读写是阻塞的,因此即使用到了Netty,也不能充分发挥它的优势。所以Netty一般用在非HTTP协议和Servlet的场景下。

    2019-05-21
    12
    114
  • “EndPoint 是通信端点,即通信监听的接口,是具体的 Socket 接收和发送处理器,是对传输层的抽象,因此 EndPoint 是用来实现 TCP/IP 协议的。”,【EndPoint是用来实现TCP/IP协议的】这个没有太明白,据我有限的知识所知,TCP/IP协议是【由操作系统实现】的,而socket只是在TCP/IP之上展现给用户层的一个接口,而EndPoint又用到了socket接口(我瞎猜的)。所以,我是否可以把这句话理解为,EndPoint利用Socket接口来将底层传来的数据转化成为HTTP格式的数据,这种行为就可以看作是对TCP/IP协议的一种间接实现。

    作者回复: 理解正确👍

    2019-05-22
    3
    61
  • ty_young
    老师,我看您说socket = endpoint.serverSocketAccept()这个是阻塞式accept;但是连接器使用的IO模型是NIO或者AIO啊,都是非阻塞的吧,只是同步或者非同步的区别吧

    作者回复: 阻塞和非阻塞说的是线程发起IO操作时,如果数据没有就绪,线程是否挂起。 同步异步说的是,应用程序与内核交互时,数据从内核空间到用户空间的拷贝,是内核主动发起还是由应用程序来触发,14篇会详细介绍。 这里的accept调用,当连接请求未到时,应用线程会挂起,因此是阻塞的,但为什么又说NIO是非阻塞呢?这是因为读取数据的线程没有挂起,因为之前已经通过Selector侦测到数据已经准备好了,到了内核空间,数据读取线程不需要等待,不需要挂起去等待数据。

    2019-06-07
    3
    49
  • 郑晨Cc
    老师有个问题想请教: tomcat既然已经使用了java的nio模型 而nio模型在linx上是基于epoll 实现的 那为什么和同样的使用epoll的nginx相比 他对于http请求处理的性能远不如nginx呢

    作者回复: Nginx/Apche一般做反向代理和处理静态HTML资源,做的事情相对来说简单,KPI就是要快,因此用C语言实现,直接调用操作系统API,充分利用操作系统的高级特性。 而Tomcat用来处理动态请求,还需要跑Java应用,因此用Java实现,因此”快“不是它主要的KPI。Java调用操作系统API要通过JNI,无形中有性能损耗。另外Tomcat通过使用Apache APR本地库来做I/O通信,性能已经跟Apache、Nginx接近了。

    2019-05-31
    3
    44
  • zhycareer
    老师,源码如何阅读效果好啊?现在源码一大堆,不知从何下手。谢谢

    作者回复: 抓主线,抓主干,每个系统中都有一个关键的核心类,紧紧抓住这些类,先不要分散,在逐步看旁枝,等你学习弄明白一个经典的系统,很多套路你就明白了。

    2019-05-21
    3
    30
  • 易儿易
    这个专栏期待已久,一出立马就订阅了,但是因为其他课程没结束,导致这个课程没有跟上老师的节奏,目前正在努力追赶,我订阅了不少课程,李号双老师是回答问题最详细最用心的一个没有之一,虽然我还没来得及提一个问题,但是已经从老师给其他学生的回复中学习了不少……给老师点赞!!!

    作者回复: 谢谢😄

    2019-06-29
    24
  • 欠债太多
    io是盲区啊,老师有什么建议呢

    作者回复: unix环境高级编程里相关章节有详细介绍,这个专栏也会图文并貌分析,你有没有发现这个专栏的内容其实蛮容易懂的😊

    2019-05-21
    24
  • 鱼乐
    老师,有个问题,根据网络协议分层模型,请求不应该是先经过Http协议,然后才经过TCP协议处理的吗,上面的图处理顺序感觉反了

    作者回复: 发送方是先http数据生成后tcp发送,接收方先tcp接收,再http解析

    2019-06-27
    3
    19
  • 学无涯
    一个service对应tomcat中部署的一个项目,一个连接器对应一个请求,这样理解对吗

    作者回复: 一个Service中可以部署多个项目呢,一个连接器对应一个监听端口,不是一个请求,一个端口上可以接收多个请求。

    2019-05-21
    3
    19
收起评论
显示
设置
留言
99+
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部