一、请求处理流程

Connector中的处理

Tomcat在初始化时会按照xml中配置来初始化不同协议的Connector,Tomcat使用ProtocolHandler来用于扩展不同的协议,包括http协议和ajp协议,在每个协议的内部又依据io类型的不同,分为bio、nio等,组合起来常用的实现类有:Http11Protocol、Http11NioProtocol、AjpProtocol、AjpNioProtocol等。 不同的io内部又是通过不同的EndPoint来处理的,如BIO的JioEndPoint、Nio的NioEndPoint
Connect中的整个请求过程如下图所示:
Tomcat请求处理过程 - 图1

Container中的处理

在Connector中对请求的协议及参数进行解析后会得到Connector包下的Request和Response对象,经过Adapter的适配,可以得到HttpServletRequest和HttpServletResponse对象,接下来会调用其所在的Service对象下的Container容器的Pipeline进行依次执行Tomcat请求处理过程 - 图2

二、Connector中对Http协议处理源码解析

BIO的处理

这里主要以bio的处理为例,主要看的是Http11Protocol中的处理,其对应的EndPoint是JioEndPoint
1.BIO中的启动
(1)初始化一个工作线程池。
注意这个线程池是Connector内部的线程池,最大线程数200
(2)初始化一个栅栏
用来限制链接次数的
(3)启动Acceptor线程
里面的过程就是new了许多Runnable的Acceptor,并开启一个线程跑这个Acceptor,接下来看看Acceptor内部的任务是什么
(4)启动一个守护线程,里面执行超时处理的任务
Tomcat请求处理过程 - 图3
2.Acceptor中run执行的任务
Acceptor是定义在AbstractEndPoint中的内部抽象类,JioEndPoint等各自进行实现.
(1)判断是否达到最大连接
(2)获取Socket
(3)处理Socket
Tomcat请求处理过程 - 图4
3.processSocket的处理
代码比较简单,封装成SocketProcessor丢给线程池进行执行(这里的线程池就是前面start中的工作线程池),接下来看看SocketProcessor中是怎么执行的

  1. 1. protected boolean processSocket(Socket socket) {
  2. 2. // Process the request from this socket
  3. 3. try {
  4. 4. SocketWrapper<Socket> wrapper = new SocketWrapper<Socket>(socket);
  5. 5. wrapper.setKeepAliveLeft(getMaxKeepAliveRequests());
  6. 6. wrapper.setSecure(isSSLEnabled());
  7. 7. // During shutdown, executor may be null - avoid NPE
  8. 8. if (!running) {
  9. 9. return false;
  10. 10. }
  11. 11. //Wrapper包装一下,封装成一个SocketProcessor并交给线程池执行
  12. 12. getExecutor().execute(new SocketProcessor(wrapper));
  13. 13. } catch (RejectedExecutionException x) {
  14. 14. log.warn("Socket processing request was rejected for:"+socket,x);
  15. 15. return false;
  16. 16. } catch (Throwable t) {
  17. 17. ExceptionUtils.handleThrowable(t);
  18. 18. // This means we got an OOM or similar creating a thread, or that
  19. 19. // the pool and its queue are full
  20. 20. log.error(sm.getString("endpoint.process.fail"), t);
  21. 21. return false;
  22. 22. }
  23. 23. return true;
  24. 24. }

4.SocketProcessor中的处理
查看其实现的run方法,核心是handler.process方法。那这个Handler又是什么东西呢?
Handler是定义在JioEndPoint中的接口,继承自AbstractEndPoint中定义的Handler接口,他有两个实现分别是ajp和http协议的,上面handler对象就是Http11ConnectionHandler,其process方法在其父类AbstractConnectionHandler中。
在里面会调用Processor的process方法,Processor接口也有很多实现类,这里对应Http11Processor,它的process方法也定义在其父类,AbstractHttp11Processor中,里面会对协议的信息进行解析,并得到org.apache.coyoteo.Request和org.apache.coyoteo.Response对象,接下来对将整个两个对象作为参数,传给Adapter的service方法,Adapter的实现类为CoyoteAdapter
该对象的service方法会将Coyote中的Request和Response转为servlet的Requst对象和Response对象,并调用Service的Contain容器Pipeline的第一个元素进行invoke

NIO的处理

NIO的处理的流程主要是多了一层Poller线程,BIO模式中每个请求都会交给线程池中的一个线程进行处理,线程会阻塞在IO等待上,而NIO则是引入了Selector,当接收到请求时会生成Channel并注册到Selector上,Selector监听到有读写事件时再去调用Handler去处理请求
Tomcat请求处理过程 - 图5