整体架构图
Connector(连接器)
功能需求:
- 监听网络端口
- 接受网络连接请求
- 读取请求网络字节流
- 根据具体应用层协议(HTTP/AJP)解析字节流,生成统一的Tomcat Request对象
- 将Tomcat Request对象转成标准的ServletRequest
- 调用Servlet容器,得到ServletResponse
- 将ServletResponse转成 Tomcat Response对象
- 将Tomcat Response对象转成网络字节流
- 将响应字节流写会服务器
分析
连接器需要完成三个高内聚的工作
- 网络通信--Endpoint
- 应用层协议解析--Processor
- Tomcat Request/Response 与 Servlet Request/Response 的转化--Adapter
处理逻辑
Endpoint负责提供字节流给Processor,Processor负责提供Tomcat Request 对象给Adapter,Adapter 负责提供ServletResponse对象给容器
由于I/O模型和应用层协议可以自由组合,所以设计了一个ProtocolHandler的接口来封装这两种变化点,
由于还存在一些稳定的部分,Tomcat设计了一系列抽象类来封装。它们的继承关系如下图所示:
ProtocolHandler组件
连接器用ProtocolHandler来处理网络连接和应用层协议,包含两个重要组件:Endpoint 和 Processor。
Endpoint
Endpoint是通信端点,即通信监听的接口,是具体的Socket接受和发送处理器,是对传输层的抽象,因此endpoint是用来实现TCP/IP协议的。
Endpoint是一个接口,对应的抽象实现类是AbstractEndpoint(org.apache.tomcat.util.net.AbstractEndpoint),而AbstractEndpoint的具体子类,比如在NioEndpoint和Nio2Endpoint中,有两个重要的子组件:Acceptor(一个实现了Runable接口的抽象类,在NioEndpoint等类中有具体实现) 和 SocketProcessor。
其中Acceptor用于监听Socket连接请求。SocketProcessor用于处理接收到的Socket请求,他事先Runnable接口,在Run方法里调用协议处理组件Processor进行处理。为了提高处理能力,SocketProcessor 被提交到线程池来执行。这个线程池叫执行器(Executor),扩展了原生的Java线程池。
Processor
如果说 Endpoint 是用来实现 TCP/IP 协议的,那么 Processor 就是用来实现HTTP协议,Processor 接受来自Endpoint的Socket,读取字节流解析成 Tomcat Request 和 Response 对象,并通过 Adapter 将其提交到容器处理,Processor 是对应用层协议的抽象。
Processor 是一个接口,定义了请求的处理等方法。它的抽象实现类 org.apache.coyote.AbstractProcessor 对一些协议共有的属性进行封装,没有对方法进行实现。具体的实现协议有 AJPProcessor 、HTTP!!Processor 等,这些具体实现类实现了特定协议的解析方法和请求处理方式。
从图中我们看到,Endpoint 接收到 Socket 连接后,生成一个SocketProcessor 任务提交到线程池去处理,SocketProcessor 的 Run 方法会调用 Processor 组件去解析应用层协议,Processor 通过解析生成 Request 对象后,会调用 Adapter 的 Service 方法。
Adapter组件
由于协议不同,客户端发过来的请求信息也不尽相同,Tomcat定义了自己的Request(org.apache.coyote.Request)类来“存放”这些请求信息。ProtocolHandler 接口负责解析请求并生成 Tomcat Request 类。但是这个Request对象并不是标准的ServletRequest,也就意味着,不能用 Tomcat Request 作为参数来调用容器。 Tomcat设计者的解决方案是引入 CoyoteAdapter(org.apache.catalina.connector.CoyoteAdapter),这是适配器模式的经典运用,连接器调用CoyoteAdapter的Service方法,传入的是 Tomcat Request 对象,CoyoteAdapter 负责将 Tomcat Request 对象转成 ServletRequest,再调用容器的 Service 方法。
作者:胡飞飞_1995
链接:https://www.jianshu.com/p/ce6d6012af63
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。