Tomcat请求流程讲授
这周部门同事要求我来进行分享一下Tomcat,我也在空余的时间对Tomcat的源码进行了阅读。
最初拿到这样一个事情,我也是比较头疼的,找不到着手点进行讲解。后来在网上查询了一些资料,对Tomcat的整体架构也有了一点了解。于是我开始着手于对Tomcat源码跟踪。
Tomcat整体是由多个组件组成,最顶层的组件是Server,一个Server代表着一个JVM实例,由Server进行初始化、销毁下面的组件。整个实例就好像一条流水线一样,由上层组件初始化下层组件,就这样一层一层的进行初始化和启动。
由上面的图可以看出,组件的组合关系。
Server包含多个Service,一个Service包含多个Connector和一个Engine;
一个Engine包含多个Host;
一个Host包含多个Context;
其中Engine、Host、Context都有共同的父类,ContainerBase。
关于每一个组件的功能,我这里不再赘述,网络上的资料有很多,大家可以自行查询。
接下来讲解关于从浏览器接收到请求的处理流程。
从名字可以看出来,Connector是用来处理关于连接的组件。
Connector包含两个主要的成员(默认协议HTTP1.1):JIOEndPoint、Http11ConnectionHandler
JIOEndPoint用来监听端口,当有新的连接过来,使用线程池进行处理。
SocketWrapper<Socket> wrapper = new SocketWrapper<Socket>(socket); wrapper.setKeepAliveLeft(getMaxKeepAliveRequests()); // During shutdown, executor may be null - avoid NPE if (!running) { return false; } getExecutor().execute(new SocketProcessor(wrapper));
实际在SocketProcessor中处理请求的是,Http11ConnectionHandler。
在Http11ConnectionHandler中经过一系列处理,最终由CoyoteAdapter对象调用service方法处理Request。
在service方法中,获得当前的Connection找到对应的Engine,将Request交给对应的Engine处理。
再由Engine根据自己的pipleline将request一层层传递下去,最终在StandardWrapper中获得filterChanin,调用servlet。
整个流程如上图所示。
其中在将request交给Engine之后的一步步处理很形象化。
上面说到,Engine,Host,Context都有一个共同的父类ContainerBase,也就是容器类。
每一个容器类都包含一个Pipeline,也就是管道,而Pipeline里包含的子元素的接口都是Valve,也就是阀门。
每一个容器类在处理Request都必须交由给当前容器的Valve来处理,再由Valve传递给下一个Container进行处理。
//=========================下面这句话是我抄来的==================================
让我们来想象一下:
当一个Request进入一个容器后, 它就在管道里面流动,波罗~ 波罗~ 波罗~ 地穿过各个阀门。在流到最后一个阀门的时候,吧唧~ 那个该死的阀门就把它扔给了子容器。 然后又开始 波罗~ 波罗~ 波罗~ ... 吧唧~.... 波罗~ 波罗~ 波罗~ ....吧唧~.... 就是通过这种方式,Request 走完了所有的容器。( 感觉有点像消化系统,最后一个地方有点像那里
//=========================上面这句话是我抄来的==================================