Tomcat架构
一、架构图
二、容器组件
server:整个servlet容器,一个tomcat对应一个server,一个server包含多个service,server在tomcat中的实现类是:StandardServer。
service:一个service包含多个connector(接受请求的协议),和一个container(容器),多个connector共享一个container容器,service在tomcat中的实现类是:StandardService。
connector:链接器,负责处理客户端请求,解析不同协议及io方式。
executor:线程池
container:包含engine,host,context,wrapper等组件
engine:servlet引擎,container容器中顶层的容器对象,一个engine可以包含多个host主机,engine在tomcat中的实现类是:StandardEngine。
host:engine容器的子容器,一个host对应一个网络域名,一个host包含多个context,host在tomcat中的实现类是:StandardHost。
context:host容器的子容器,表示一个web应用,context在tomcat中的实现类是:StandardContext。
wrapper:tomcat中最小的容器单元,web应用中的servlet会被包装成一个wrapper,wrapper在tomcat中的实现类是:StandardWrapper。
三、NIO架构
1、Connector主要负责用来初始化具体应用协议的处理类ProtocolHandler,应用协议包括 http 协议(http/1.1 版本,http/1.0 版本),AJP 协议(AJP/1.3 版本)。
2、ProtocolHandler代表不同协议处理的实现类,对于 tomcat NIO来说,实现类为 Http11NioProtocol,用来处理 http/1.1 协议。对于普通的 http/1.0 版本协议来说,实现类为 Http11Protocol 。对于AJP/1.3 版本协议来说,为 AjpAprProtocol 和 AjpNioProtocol 这个两个类。
3、AbstractEndpoint 类是属于 Http11NioProtocol 类,其主要用来处理底层socket的连接,对于 tomcat NIO的实现类来说是 NioEndpoint。
4、Poller 类属于NioEndpoint,主要监测 epoll 模型里注册原始 socket 上的读写事件是否发生。
5、NioSelectorPool 类属于 NioEndpoint ,当数据需要多次读写的时候,监测注册在原始 socket 上的读写事件是否发生。
6、NioBlockingSelector 类属于 NioSelectorPool 类,对于监测注册在原始 scoket 上的读写事件,delegate 给 NioBlockingSelector 处理。
7、BlockPoller 类属于 NioBlockingSelector 类,实现具体的监测读写事件的逻辑。
8、SocketWrapper 类封装了原始 socket ,提供封装的 socket 读写操作。
9、ConnectionHandler 类属于 Http11NioProtocol 类,主要对 SocketWrapper 类进行操作,整个 tomcat NIO 的处理框架就仅仅只有一个 ConnectionHandler 实例,是全局的,也就是说所有的连接 SocketWrapper 都由这个实例处理。
10、Http11Processor,该类由 ConnectionHandler 实例调用,会把接收到的 SocketWrapper 封装成 tomcat 的 Request 和 Response 对象。
11、CoyoteAdapter,该类负责把 Http11Processor 封装的 tomcat Request 和 Response 对象给转换成 HttpServletRequest/HttpServletResponse 对象,并完成对 servlet API 的调用。
ConnectionHandler 实例中还有一个 Map 类型的对象,key 为SocketWrapper 类型,value 为 Http11Processor 类型。也就是说为每一个连接都分配了处理类 Http11Processor ,可以保存连接的状态信息。
四、数据处理
在tomcat NIO的实现里,会有一系列处理数据读写的类。并且 tomcat 也实现了servlet 标准,是 servlet 容器。所以会把处理数据读写的类封装成标准的HttpServletRequest 和HttpServletResponse 实现,从而完成从原始 socket 连接请求到 servlet API 的调用。
对于请求 Request 相关的类,展示如下图:
1、HttpServletRequest 类,代表标准 servlet API 中对于 Request 的具体的定义,其实现类为org.apache.catalina.connector.Request 。
2、HttpServletResponse 类,代表标准 servlet API 中对于 Response 的具体的定义,其中具体的实现类为org.apache.catalina.connector.Response 。
3、Connector类,org.apache.catalina.connector.Request类的属性之一,就是上面所讲的容器组件。
4、coyoteRequest ,org.apache.coyote.Request类的实例,是 tomcat 对连接请求的封装,同时里面也包含 http method ,uri ,querystring ,host ,port 等 items 的封装。
5、CoyoteInputStream,是 tomcat 对于输入流的包装。
6、InputBuffer 类,用来完成请求数据的读取。其中包含 Bytebuffer 和 CharBuffer 作为字节和字符读取缓冲区,默认大小为1028*8 bit ,即8KB。
7、coyoteResponse,org.apache.coyote.Response的实例,是 tomcat 对于对连接响应的封装。
8、Http11InputBuffer 类,主要用于完成请求数据的读取,其中包含 Bytebuffer 作为字节读取缓冲区,包含 SocketInputBuffer 辅助类用于完成到 Bytebuffer 字节缓冲区的读操作。
9、NioSocketWrapper 类,封装了原始的 scoket ,提供封装的 socket 读写操作。
10、NioSelectorPool 类,当数据需要多次读写的时候,监测注册在原始 scoket 上的读写事件是否发生。
11、readLatch和writeLatch,CountDownLatch类的实例,均是属于 NioSocketWrapper 类的属性。用于当数据不可读,或者不可写的时候对 tomcat io 线程的阻塞,即如果数据不可读写,tomcat io 线程会分别在 readLatch 实例和 writeLatch 实例上等待。
12、poller,主要监测 epoll 模型里注册原始 scoket 上的读写事件是否发生。里面包含事件队列SynchronizedQueue ,java NIO 事件轮询对象 selector,同时还包含了并发事件计数器 weakupCounter。
13、NioChannel,对原始 java NIO 对象 ScoketChannel 的封装。
14、SocketBufferHandler 类,主要是用于进行封装原始 java NIO ScoketChannel 对象的读写 buffer 。其内部有 DirectBuffer 类型的读缓冲与写缓存,这里的 DirectBuffer 是堆外内存,而不是 jvm 内存,从而提高了读写效率。
对于请求 Reponse 相关的类,展示如下图:
1、CoyoteOutputStream,是 tomcat 对于输出流的包装。
2、OutputBuffer 类,用来完成响应数据的写操作。其中包含Bytebuffer 和 CharBuffer 作为字节和字符写操作缓冲区,默认大小为1024*8 bit,即8KB。
3、Http11OutputBuffer 类,主要用于完成响应数据的写操作,其中包含 Bytebuffer 作为 header 字节写缓冲区,包含 SocketOutputBuffer 辅助类用于完成写操作。
参考链接:https://blog.csdn.net/weixin_46073333/article/details/107054348?spm=1001.2014.3001.5501