探究tomcat7源码的connector

来源:互联网 发布:搞笑相机软件大全 编辑:程序博客网 时间:2024/05/21 18:50

了解tomcat的整体启动后,我们再来聊一聊tomcat的connector,也就是负责连接和协议处理的模块

1、下图笔者将主要类图提取出来,先看看Connector的UML类图


Connector:不用多说,就是连接器本身,包含两个组件Adapter和ProtocolHandler

Adapter:提供service方法,负责invoke Container中的具体业务代码,将ProtocolHandler的数据封装成javax.servlet.http.HttpServletRequest与javax.servlet.http.HttpServletReponse,将http请求数据转化为业务型数据,如构建sessionID、解析URL中的参数、MessageBytes解码等,tomcat给了默认实现CoyoteAdapter实现

ProtocolHandler:负责协议发连接的接口,并提供基础的解析,如http头部、内容长度、长连接维护等。抽象实现为AbstractProtocol,AbstractProtocol的具体实现有AjpAprProtocol、AjpNioProtocol、AjpProtocol、Http11NioProtocol、Http11Protocol、Http11AprProtocol(tomcat8以后可能会更多)等,各个实现类分别实现不同的应用层协议和传输层协议

AbstractEndpoint:负责底层的socket连接,如端口绑定与解绑、长连接管理、ssl连接、处理socket延迟、控制tcp连接数、管理执行器(Executor)等,具体实现类有AprEndpoint、JIoEndpoint、NioEndpoint等

Executor:负责监听端口数据,维护线程池,并将监听的socket放到数据放到线程池运行,ThreadPoolExecutor是其中一个具体实现类,也是tomcat7默认实现类

AbstractEndpoint.Acceptor:实现Runnable接口,单条线程等待socket的连接

AbstractEndpoint.Handler:协议状态管理,里面提供了socket状态枚举、回收等方法,主要用于维护socket的状态

AbstractConnectionHandler:继承的基础上新增了创建process、管理process的功能,并且能够根据不同的socket状态创建process

Process:具体的socket上层的协议处理任务,并且构造成org.apache.coyote.Request、org.apache.coyote.Response,管理Comet技术、Async技术、长连接管理(此处是协议上层的长连接,并不是socket层的长连接),具体实现类有AbstractAjpProcessor、AbstractHttp11Processor

AbstractInputBuffer:负责HTTP协议解析,如将解析请求头转化为MimeHeaders对象、将post数据封装成InputStream数据等,具体实现类有InternalAprInputBuffer、InternalInputBuffer、InternalNioInputBuffer等


2、把这些基本构件及其大概的功能搞清楚后,下面我们就来分析一次http请求过来了服务端都干了些什么

先提供一张笔者画的时序图


首先AbstractEndpoint在启动时会创建线程池监听客户端请求,一个线程对应一个Acceptor,通过强制子类实现getLocalPort、bind、startInternal、createAcceptor等方法实现具体的socket连接,每个Acceptor里面的run方法都会监听同一个serverSocket。AbstractEndpoint还会提供startAcceptorThreads方法启动所有线程

startAcceptorThreads方法如下图


如图可知,每个Acceptor都需要createAcceptor方法创建,我们再来看看createAcceptor方法


可知,这个方法需要具体的子类实现,我们看看其中一个子类JIoEndpoint的实现

我们再看看JIoEndpoint是如何实现这个Acceptor子类的


这里我们看到,Acceptor的实现里面会去监听serverSocket,也就是所有的Acceptor都会监听同一个serverSocket,这样就实现了并发请求。所以正常情况下,如果没有连接到来时线程会阻塞在这里。

下面我们继续看看如果有新的连接过来了会怎么样


我们看到运行了processSocket方法,我们再具体看看这个方法


上图可知,我们在代码的533行看到直接将socket扔到了Executor里去处理,而我们之前说过,tomcat7的默认实现是ThreadPoolExecutor处理,因此我们可以得出结论:维持tcp连接的线程与‘处理这个连接’的线程不是同一线程

接下来我们再看看这个‘处理这个连接’线程做了些什么,也就是SocketProcessor这个东西


我们看到,他会做一些socket的连接状态判断,如果不是关闭状态的,则会运行handler的process方法,我们继续寻找这个process的具体实现类的方法,前面,根据以上的UML类图可查询到,这个实现类在AbstractProtocol里面有抽象的实现AbstractConnectionHandler,主要用于协调socket处理与上层协议处理,我们看看他是如何协调的


我们看到这里是通过创建的processor来协调的,前面知道processor主要用于上层协议的处理,这里显然已经开始从socket层到应用层协议转化了,我们先看看这个processor是如何生成的。经过查找,我们知道这个对象的生成是通过抽象方法createProcessor获取的,也就是说需要AbstractConnectionHandler的子类去实现创建这个processor的方法,我们挑选其中一个子类AjpProtocol.AjpConnectionHandler去看看是如何实现的


创建的是一个AjpProcessor的实例,我们就再进这个AjpProcessor的process方法里面看看是如何解析这个协议的


我们看到了调用了adapter的service方法而在上面我们知道,Tomcat7默认的Adapter实现是CoyoteAdapter,所以我们只需要查看CoyoteAdapter的service方法即可


我们看到了,服务由这里调用了Container的方法,那就是tomcat的另一个模块了


3.关于AbstractInputBuffer

可能有细心的读者发现了,上图中的AbstractInputBuffer并未出现在请求的流程中,这是因为笔者举的例子是AJP协议,所以上面挑选的process协议处理类为AjpProtocol.AjpConnectionHandler,而在HTTP的协议里面可以看到AbstractInputBuffer参与解析

原创粉丝点击