一,Tomcat要实现的两个核心功能:
处理Socket连接,负责网络字节流与Request和Response对象的转化
加载和管理Servlet,具体处理Request请求
二,Tomcat设计了两个核心组件:
连接器(Connector):负责对外交流
容器(Container):负责内部处理
三,Tomcat支持的多种 I/O 模型和应用层协议
1,I/O模型:
NIO:非阻塞I/O,采用Java NIO类库实现
NIO2:异步 I/O ,采用JDK7最新的NIO2类库实现
APR:采用Apache可移植运行库实现,是C/C++编写的本地库
2,应用层协议:
HTTP/1.1:大部分Web应用采用的访问协议
AJP:用于和Web服务器集成(如APache)
HTTP/2:HTTP2.0提升了Web性能
3,单独的连接器或容器都不能对外提供服务,需要把它们组装起来才能工作,组装后的这个整体叫Service组件。(一个容器可能对接多个连接器)。
注意:Service本身没有做什么事情,只是在连接器和容器外面多包了一层,把它们组装在一起。Tomcat内可能有多个Service,通过在Tomcat中配置多个Service,可以实现通过不同的端口号来访问同一台机器上部署的不同应用。
最顶层是Server(Server指一个Tomcat实例),一个Server中有一个或多个Service,一个Service中有多个连接器和一个容器,连接器和容器之间通过标准的ServletRequest和ServletResponse通信。
四,连接器
连接器对Servlet容器屏蔽了协议和I/O模型。无论是HTTP还是AJP,在容器中获取到的都是一个标准的ServletRequest对象。
1,连接器的功能需求
监听网络端口
接受网络连接请求
读取请求网络字节流
根据应用层协议(HTTP/AJP)解析字节流,生成统一的Tomcat Request对象
将 Tomcat Request 对象转成标准的 ServletRequst
调用Servlet容器,得到ServletResponse
将ServletResponse转成 Tomcat Response 对象
将 Tomcat Response 转成网络字节流
将响应字节流写回给浏览器
2,连接器子模块(模块化设计)
2.1,设计原则
高内聚:相关度比较高的功能要尽可能集中,不要分散
低耦合:两个相关的模块要尽可能减少依赖的部分和降低依赖的程度,不要让两个模块产生强依赖。
3,经过分析,连接器需要三个高内聚功能:
网络通信
应用层协议解析
Tomcat Request/Response 与 Serv...
极客时间版权所有: https://time.geekbang.org/column/article/963
Tomcat Request/Resopnse 与 ServletRequest/ServletResponse的转化
4,Tomcat提供了三个组件来实现这三个功能
4.1,EndPoint:
EndPoint是通信端点,是通信监听的接口,是具体的Socket接收和发送处理器,是对传输层的抽象,因此,EndPoint是用来实现TCP/IP协议的。
EndPoint是一个接口, EndPoint(接口) ------> AbstractEndPoint(抽象实现类) ------>NioEndPoint(具体子类)。在NioEndPoint中有两个组件:Acceptor 和 SocketProcessor。
Acceptor用来监听Socket连接请求。SocketProcessor用来处理接收到的Socket请求,它实现了Runnable接口,在Run方法里调用协议处理组件Processor进行处理。(为了提高处理能力,SocketProcessor被提交到线程池来执行)
4.2,Processor:
Processor接收来自EndPoint的Socket,读取字节流解析成 Tomcat Request和 Response对象,并通过Adapter将其提交到容器中。是对用应用层的抽象,Processor用来实现HTTP协议的。
Processor是一个接口。Processor(接口,定义了请求的处理方法) ----->AbstractProcessor(抽象实现类,对协议共有的属性进行封装,没有对方法进行实现) ------>HTTP11Processor(具体实现类,实现了特定协议的解析方法和请求处理方式)。
由于I/O模型和应用层协议可以自由组合,比如 NIO + HTTP 或者 NIO2 + AJP。Tomcat的设计者把网络通信和应用层协议解析放在一起,设计出了ProtocolHandler的接口来封装这两种变化点。并且各种协议和通信模型的组合有相应的具体实现类。(比如:Http11NioProtocol 和 AjpNioProtocol)
4.3,Adapter:
ProtocolHandler接口负责解析请求并生成Tomcat Request类。但是这个Request对象不是标准的ServletRequest,所以不能用Tomcat Request作为参数来调用容器。Tomcat设计者的解决方案是引入 CoyoteAdapter,这是适配器设计模式。连接器调用CoyoteAdapter的Service方法,传入的是Tomcat Request对象,CoyoteAdapter负责将Tomcat Request转成ServletRequest,再调用容器的Service方法。
五,连接器组件图:
EndPoint接收到 Socket连接后,生成一个 SocketProcessor 任务提交到线程池去处理,SocketProcessor的Run方法会调用Processor组件去解析应用层协议,Processor通过解析生成Request对象后,会调用Adapter的Service方法。