6张时序图!谈谈Tomcat请求处理流程
Posted 顶级程序员
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了6张时序图!谈谈Tomcat请求处理流程相关的知识,希望对你有一定的参考价值。
-
绘制图形使用的工具是 PlantUML + Visual Studio Code + PlantUML Extension
-
Overview -
Connector Init and Start -
Requtst Process -
Acceptor -
Poller -
Worker -
Container -
At last
Overview
-
Connector 启动以后会启动一组线程用于不同阶段的请求处理过程。 -
Acceptor 线程组。用于接受新连接,并将新连接封装一下,选择一个 Poller 将新连接添加到 Poller 的事件队列中。 -
Poller 线程组。用于监听 Socket 事件,当 Socket 可读或可写等等时,将 Socket 封装一下添加到 worker 线程池的任务队列中。 -
worker 线程组。用于对请求进行处理,包括分析请求报文并创建 Request 对象,调用容器的 pipeline 进行处理。
-
Acceptor 、 Poller 、 worker 所在的 ThreadPoolExecutor 都维护在 NioEndpoint 中。
Connector Init and Start
-
initServerSocket() ,通过 ServerSocketChannel.open() 打开一个 ServerSocket,默认绑定到 8080 端口,默认的连接等待队列长度是 100, 当超过 100 个时会拒绝服务。我们可以通过配置 conf/server.xml 中 Connector 的 acceptCount 属性对其进行定制。 -
createExecutor() 用于创建 Worker 线程池。默认会启动 10 个 Worker 线程,Tomcat 处理请求过程中, Woker 最多不超过 200 个。我们可以通过配置 conf/server.xml 中 Connector 的 minSpareThreads 和 maxThreads 对这两个属性进行定制。 -
Pollor 用于检测已就绪的 Socket。 默认最多不超过 2 个, Math.min(2,Runtime.getRuntime().availableProcessors()); 。我们可以通过配置 pollerThreadCount 来定制。 -
Acceptor 用于接受新连接。默认是 1 个。我们可以通过配置 acceptorThreadCount 对其进行定制。
Requtst Process
Acceptor
-
Acceptor 在启动后会阻塞在 ServerSocketChannel.accept(); 方法处,当有新连接到达时,该方法返回一个 SocketChannel。 -
配置完 Socket 以后将 Socket 封装到 NioChannel 中,并注册到 Poller , 值的一提的是,我们一开始就启动了多个 Poller 线程,注册的时候,连接是公平的分配到每个 Poller 的。 NioEndpoint 维护了一个 Poller 数组,当一个连接分配给 pollers[index] 时,下一个连接就会分配给 pollers[(index+1)%pollers.length]. -
addEvent() 方法会将 Socket 添加到该 Poller 的 PollerEvent 队列中。 到此 Acceptor 的任务就完成了。
Poller
-
selector.select(1000) 。当 Poller 启动后因为 selector 中并没有已注册的 Channel ,所以当执行到该方法时只能阻塞。所有的 Poller 共用一个 Selector,其实现类是 sun.nio.ch.EPollSelectorImpl -
events() 方法会将通过 addEvent() 方法添加到事件队列中的 Socket 注册到 EPollSelectorImpl ,当 Socket 可读时, Poller 才对其进行处理 -
createSocketProcessor() 方法将 Socket 封装到 SocketProcessor 中, SocketProcessor 实现了 Runnable 接口。 worker 线程通过调用其 run() 方法来对 Socket 进行处理。 -
execute(SocketProcessor) 方法将 SocketProcessor 提交到线程池,放入线程池的 workQueue 中。 workQueue 是 BlockingQueue 的实例。到此 Poller 的任务就完成了。
Worker
-
worker 线程被创建以后就执行 ThreadPoolExecutor 的 runWorker() 方法,试图从 workQueue 中取待处理任务,但是一开始 workQueue 是空的,所以 worker 线程会阻塞在 workQueue.take() 方法。 -
当新任务添加到 workQueue 后, workQueue.take() 方法会返回一个 Runnable ,通常是 SocketProcessor , 然后 worker 线程调用 SocketProcessor 的 run() 方法对 Socket 进行处理。 -
createProcessor() 会创建一个 Http11Processor , 它用来解析 Socket,将 Socket 中的内容封装到 Request 中。 注意这个 Request 是临时使用的一个类,它的全类名是 org.apache.coyote.Request , -
postParseRequest() 方法封装一下 Request ,并处理一下映射关系 (从 URL 映射到相应的 Host、 Context、 Wrapper )。 -
CoyoteAdapter 将 Rquest 提交给 Container 处理之前,并将 org.apache.coyote.Request 封装到 org.apache.catalina.connector.Request ,传递给 Container 处理的 Request 是 org.apache.catalina.connector.Request。 -
connector.getService().getMapper().map(), 用来在 Mapper 中查询 URL 的映射关系。 映射关系会保留到 org.apache.catalina.connector.Request 中, Container 处理阶段 request.getHost() 是使用的就是这个阶段查询到的映射主机,以此类推 request.getContext()、 request.getWrapper() 都是。 -
connector.getService().getContainer().getPipeline().getFirst().invoke() 会将请求传递到 Container 处理,当然了 Container 处理也是在 Worker 线程中执行的,但是这是一个相对独立的模块,所以单独分出来一节。
Container
-
需要注意的是,基本上每一个容器的 StandardPipeline 上都会有多个已注册的 Valve ,我们只关注每个容器的 Basic Valve 。其他 Valve 都是在 Basic Valve 前执行。 -
request.getHost().getPipeline().getFirst().invoke() 先获取对应的 StandardHost ,并执行其 pipeline 。 -
request.getContext().getPipeline().getFirst().invoke() 先获取对应的 StandardContext , 并执行其 pipeline 。 -
request.getWrapper().getPipeline().getFirst().invoke() 先获取对应的 StandardWrapper ,并执行其 pipeline 。 -
最值得说的就是 StandardWrapper 的 Basic Valve , StandardWrapperValve -
allocate() 用来加载并初始化 Servlet,值的一提的是 Servlet 并不都是单例的,当 Servlet 实现了 SingleThreadModel 接口后, StandardWrapper 会维护一组 Servlet 实例,这是享元模式。 当然了 SingleThreadModel 在 Servlet 2.4 以后就弃用了。 -
createFilterChain() 方法会从 StandardContext 中获取到所有的过滤器,然后将匹配 Request URL 的所有过滤器挑选出来添加到 filterChain 中。 -
doFilter() 执行过滤链, 当所有的过滤器都执行完毕后调用 Servlet 的 service() 方法。
Reference
-
《How Tomcat works》 -
《Tomcat 架构解析》-- 刘光瑞 -
Tomcat-9.0-doc -
apache-tomcat-9.0.0.M22-src -
tomcat 架构分析 (connector NIO 实现)
-END-
中秋特惠 | 粉丝福利
原价199元人工智能精品课
体验价仅需¥9.9
以上是关于6张时序图!谈谈Tomcat请求处理流程的主要内容,如果未能解决你的问题,请参考以下文章