Tomcat连接

Tomcat连接

概述

本文内容以常用的NIO连接处理为例,其他连接处理流程类似。同时,时序图中的类多数都为NioEndpoint类的内部类。

处理时序图

这里写图片描述

时序图说明

Connector

服务器端的一个服务端口的抽象,是处理连接的最上层对象。可以定义某个服务端内最大连接数,最大线程数,监听端口等。此类通过server.xml中的配置进行实例化并通过配置指定相应的协议(protocol属性,协议中包含协议对应的连接处理器和协议处理器),并与service组合。

以上时序图可以大致理解为一个socket请求访问Connector时,Connector内部的处理流程。

Connector在生命周期的init阶段会通过协议处理器内的Endpoint监听指定服务端口

Http11NioProtocol

由server.xml中声明Connector时指定,ProtocolHandler接口的实现类。顾名思义,协议。其内部包含就收连接相关的endpoint、处理连接的ConnectorHandler、处理协议内容的Porcessor等属性,并会设置协议相关的固定属性,例如http协议头最大长度等属性。

Acceptor

用于接收客户端请求、并根据最大连接数控制是否阻塞请求的线程对象。在启动阶段启动,默认(通常)情况下只有一个线程启动。用于处理ServerSocketChannel接收到的SocketChannel。在run()方法中,会首先判断是否达到最大连接数(Connector的配置),达到则会阻塞线程直到释放连接(使用LimitLatch实现)。

获取到的SocketChannel会交由NioEndpoint.setSocketOptions(SocketChannel)处理。

NioEndpoint

专门用于处理请求的服务端点,内保包含Acceptor、Poller以及处理请求的工作线程等对象。NioEndpoint对象自身包含如下关键方法:

  • bind():生命周期init阶段会绑定服务区端口并配置相应的ServerSocketChannel,并启动NioSelectorPool内的线程。初始化acceptor线程个数,默认为1。
  • startInternal():启动时,启动多个Poller线程,个数为2和CPU个数的最小值。启动Acceptor线程。根据所属Connector的设置初始化LimitLatch。
  • setSocketOptions(SocketChannel):将SocketChannel传入参数设置为非阻塞方便后续注册到Selector上,优先从nioChannels并发队列获取NioChannel对象,获取不到会将请求的SocketChannel和NioBufferHandler(处理读写ByteBuffer)封装为NioChannel对象,并将对象存放到nioChannels阻塞队列中。最后将NioChannel对象以轮询的方式注册到Poller线程,待Poller处理。
  • processSocket():处理读或写就绪的socket,将NioChannel和其SOCKET状态封装为SocketPorcessor对象实例,并提交到http-nio-端口号-exec-n线程池中执行,此线程池使用的阻塞队列最大长度限制为MAX_INT

Poller

用于轮询连接,并根据连接状态进行处理的轮询器。轮询器的个数为1或2个,一般为2个。通过原子自增数字求余数来保证连接均匀分布到各个轮询器上

  • register():将NioChannel、KeyAttachment(SocketChannel向selector注册时的附加信息,主要保存NioChannel实例)以及操作数为OP_REGISTER实例化或者重置PollerEvent对象,并将PollerEvent添加到Poller.events队列中。同时通过wakeupCounter原子对象来控制是否调用selector.wakeup(),此处是先调用wakeup,保证后续的selector.select()可以立即返回不会阻塞
  • run():轮训执行Poller.events队列中的PollerEvent线程。通过selector和wakeupCounter来控制是否阻塞等待返回。最终通过selector.selectNow()或selector.select(selectorTimeout)获取就绪的SelectionKey以及相应的注册到selector时的KeyAttachment。
  • processKey():用于处理selector返回的已经就绪的socket,注销关注操作数。交由NioEndPoint.processSocket()后续处理。

PollerEvent

按照注释是用于缓存NioChannel避免被GC。

run()方法逻辑:用于对操作数为1000000000的PollerEvent,将SocketChannel已读就绪的方式注册到轮询器的Selector中,否则获取Selector中SocketChannel关注的事件,并去掉操作数中的1000000000。执行完成后将EventPoller缓存进eventCache待后续使用。

SocketProcessor

最常看到的工作线程(http-nio-端口号-exec-n)的入口,从selector中获得自身NioChannel持有的SocketChannel的key,根据socket的handshake状态(NIO永远为true),以及当前实例的status属性,将KeyAttachment和status提交给调用协议处理器的连接处理器处理。

Http11ConnectionHandler

协议中的连接处理器,判断socketChannel是否存在、重用或新建协议处理器以及将NioChannel交由协议处理器处理。在创建协议处理器时,会同时把协议处理器注册到JMX。

Http11NioProcessor

协议中包含的协议处理器,用于解析SocketChannel中读取的信息转化为Request对象,并交由后续容器处理。通过process()方法进行处理:

  • 处理器在实例化时会实例化request、response、IO Buffer等相关对象实例。
  • 通过InputBuffer解析http请求头以及请求URL中的参数。POST的参数在第一次获取参数时一次性从InputBuffer中获取,通过&分割不同key-value,通过=分割key和value。
  • 根据解析的信息设置Request的属性
  • 将request和response传入adapter进行后续处理

InternalNioInputBuffer

用于对HTTP请求头进行解析、解码。通过parseRequestLine()方法以及parseHeaders()方法解析,解析方法为逐个读取字符,严格按照Http协议头的定义,逐个字符判断处理,对于空格、换行进行特殊处理、解析。

CoyoteAdapter

用于根据request的URL将协议处理器解析出来的request匹配到指定的Wrapper容器并保存到request对象中,并将request和response提交给容器中的Pipeline(多个Valve组成的通道,链式处理)处理。

ContainerPipeline

这里的ContainerPipeline指代的是Tomcat中整个容器体系内的Pipeline,处理流程如下图:
pipeline时序图
前文介绍过Tomcat内部结构以及容器内部的Pipeline结构以及其内部basic、first变量的作用,此处不再赘述,只是就整体流程介绍:

  1. CoyoteAdapter会首先调用service对象对应的容器Engine内的pipeline。根据pipeline的特性,会从first开始逐个调用Valve并最终通过StandardEngineValve调用子容器Host内的pipeline。
  2. 同上,Host内的pipeline会逐个调用Valve,最终通过StandardHostValve调用子容器Context内的pipeline。
  3. 同上,Context内部的pipeline会逐个调用Valve,最终通过StandardContextValve调用request中保存的Wrapper容器的pipeline。
  4. 同时,Wrapper内部的pipeline会逐个调用Valve,最终通过StandardWrapperValve实例化过滤器链(ApplicationFilterChain)并调用过滤器链的dofilter方法。
  5. ApplicationFilterChain的dofilter方法会逐个调用web.xml中声明的、匹配的Filter对象的doFilter方法,并在所有Filter都执行完后,才执行Servlet的service方法
  6. Filter中doFilter方法链式执行的实现方式是ApplicationFilterChain中持有Filter总个数和当前Filter的索引值,当总数>索引值时,就执行下一个Filter的dofilter方法,否则执行Servlet的service方法。
  7. 一般情况下,Wrapper容器中的Servlet就是我们编写的服务Servlet或者Spring、Strust等web框架的分发Servlet。

猜你喜欢

转载自blog.csdn.net/woshismyawei/article/details/79714690