接收HTTP请求的服务器即HTTP服务器,接收请求并且调用服务端程序处理请求。
直接调用业务类是紧耦合的。因此加入一层Servlet容器,由Servlet容器调用业务类,业务类都要实现Servlet接口实现业务解耦。Servlet接口+Servlet容器 = Servlet规范。
综上,Tomcat其实分为接收请求的连接器部分和业务处理的容器两大部分。
注意,一个容器可能对应多个连接器。连接器和容器都不能单独对外提供服务,组装起来成为Service组件提供服务。
因此一个Tomcat即Server,对应一或多个Service。这样在一个Tomcat实例上可以使用不同端口号暴露不同应用。
连接器——Coyote
HTTP服务器即这里的连接器部分叫Coyote。负责处理Socket请求,负责网络字节流和Request、Response的对象转换。概括来说主要有3个功能。
3个模块
1. 网络通信
监听网络端口、接收网络连接请求。
2. 应用层协议解析
读取Socket请求字节流。Tomcat Response转成Socket响应字节流,响应字节流给客户端。根据应用层协议(如HTTP)解析字节流,生成统一Tomcat Request对象。
3. Request、Response对象转化
Tomcat Request、Response和ServletRequest和ServletResponse转化。 将Tomcat Request对象转成ServletRequest。调用Servlet容器得到ServletResponse,将ServletResponse转为Tomcat Response。
有了以上3个模块的认知,下面我们可以再详细介绍连接器的3大组件。
3大组件
1. [Abstract]Endpoint
Endpoint对应网络通信功能,即通信监听接口,接收和发送Socket,对传输层进行抽象。 Tomcat是提供了抽象类AbstractEndpoint来实现这个Endpoint的功能,具体内部2个类。
-
Acceptor 监听Socket连接请求
-
SocketProcessor 处理Socket请求,开辟线程调用下一步协议处理组件Processor。
为了提高能力, SocketProcessor被提交到线程池执行,这个线程池Executor也叫执行器。SocketProcessor是任务,提交到线程池中去处理,其中的run方法会调用Processor组件解析应用层协议。
Tomcat8.5之后默认NIO、还支持异步IO、APR。
2. Processor
Processor对应应用层协议解析,作为协议处理接口,实现应用层协议。
接收来自前面的组件Exdpoint的Socket,读取字节流解析成Tomcat的Request和Response对象,通过Adapter将其交给容器处理。
支持HTTP1.1、HTTP2、AJP。
3. Adapter
适配器模式,不同的协议请求的信息也不同。Tomcat定义自己的Request封装请求信息,由CoyoteAdapter适配器将Request、Response转化为标准的ServletRequest、ServletResponse,调用容器的service方法。
其中处理传输层协议的组件与处理应用层的组件AbstractEndpoint、Processor封装为协议接口。根据应用层+传输层IO+Protocol实现了6个类:
- AjpNioProtocol
- AjpAprProtocol
- AjpNio2Protolcol
- Http11NioProtocol
- Http11Nio2Protocol
- Http11AprProtocol
容器Container
Servlet容器即Container容器。加载和管理Servlet,具体处理Request请求,并响应。
Servlet容器工作流程
-
定位Servlet
Servlet容器接收到的请求是HTTP服务器封装后的ServletRequest,被调用的方法是Servlet的service方法。根据请求Url和Servlet映射关系,找到对应Servlet。
-
加载Servlet&调用Servlet
如果Servlet还没被加载,那么通过反射创建这个Servlet,并调用Servlet的init方法初始化后,再调用service方法,处理请求。
-
如果有Servlet,那么直接调用service处理请求。
-
处理了请求后,返回ServletResponse给HTTP服务器。HTTP服务器负责响应给客户端。