目录
1.Tomcat容器构成
2.Tomcat是如何接收一次请求的
从上图可知Tomcat中有很多容器,包括Server、Service、Connector等。其中Connector正是与HTTP请求处理相关的容器。Connector的实现分为以下几种:
- Http Connector:基于HTTP协议,负责建立HTTP连接。它又分为BIO Http Connector与NIO Http Connector两种,后者提供非阻塞IO与长连接Comet支持。
- AJP Connector:基于AJP协议,AJP是专门设计用于Tomcat与HTTP服务器通信定制的协议,能提供较高的通信速度和效率。如与Apache服务器集成时,采用这个协议。
- APR HTTP Connector:用C实现,通过JNI调用的。主要提升对静态资源(如HTML、图片、CSS、JS等)的访问性能。
具体源码实现:setProtocol函数的入参protocol在server.xml中配置
setProtocol函数代码作用:主要判断了是否启用Apr模式,如果启用,那么"HTTP/1.1"就将org.apache.coyote.http11.Http11AprProtocol这个类作为Handler,其他协议以此类推。
我们可以看到在关闭Apr模式的时候,配置"HTTP/1.1"是将Http11NioProtocol类作为Handler,Http11NioProtocol为NIO模式连接器,因为NIO模式涉及到生产者消费者模式,代码略复杂,下文我们将用Tomcat7中的Http11Protocol类(BIO模式)来剖析一次请求的过程。
可以看到Http11NioProtocol在构造的时候初始化了一个JIoEndpoint(通信端点)
在JIoEndpoint类中我们看到其内部类Acceptor启动一个线程,一直在循环接收请求
跟进processSocket方法可以看到用线程池做了一次调用
跟进内部run方法下finally块中handler.process(socket, SocketStatus.DISCONNECT);开始调用handler处理请求
继续跟进发现其调用super.process(socket, status);
最终我们一路跟进发现调用到AbstractHttp11Processor类中 process()方法
在这个方法中我们可以看到,tomcat已经开始对request对象进行赋值。
最终将请求交给adapter去处理,
最终调用connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);将请求交给Engine的Pineline处理
最终通过责任链模式,一步步的调用到ApplicationFiterChain执行Servlet的service方法。
最终在HttpServlet类中去调用doGet方法,继而调用到我们继承自HttpServlet自定义的doGet方法。
借鉴博文:阿里大佬总结的tomcat源码,写的非常好
Tomcat源码分析——生命周期管理 - 泰山不老生 - 博客园
Tomcat源码分析——请求原理分析(上) - 泰山不老生 - 博客园