Tomcat9请求处理流程与启动部署过程的示例分析

技术Tomcat9请求处理流程与启动部署过程的示例分析这篇文章主要为大家展示了“Tomcat9请求处理流程与启动部署过程的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下

本文主要向大家展示“Tomcat9请求处理流程和启动部署流程示例分析”,简单易懂,条理清晰,希望能帮大家解惑。让边肖带领大家学习和研究文章《Tomcat9请求处理流程和启动部署流程实例分析》。

Overview

Tomcat9请求处理流程与启动部署过程的示例分析

连接器启动后,将为请求处理的不同阶段启动一组线程。

接受者线程组用于接受新连接,封装新连接,并选择一个轮询器将新连接添加到轮询器的事件队列中。

轮询线程组。用于监视套接字事件,当套接字可读或可写时,等等。封装套接字并将其添加到工作线程池的任务队列中。

工作线程组。用于处理请求,包括分析请求消息和创建请求对象,调用容器的管道进行处理。

接受者、轮询者和工作者所在的线程池执行器在NioEndpoint中维护。

Connector Init and Start

Tomcat9请求处理流程与启动部署过程的示例分析

ServerSocket(),通过ServerSocketChannel.open()打开一个服务器套接字,默认绑定到端口8080,默认连接等待队列长度为100。当超过100个时,服务将被拒绝。我们可以通过在conf/server.xml中配置连接器的acceptCount属性来自定义连接器

CreateExecutor()用于创建工作线程池。默认情况下,将启动10个Worker线程,在Tomcat处理请求期间,最多不会超过200个woker。我们可以通过在conf/server.xml中配置连接器的minSpareThreads和maxThreads来自定义这两个属性

轮询器用于检测就绪套接字。默认情况下不超过2个,math.min (2,runtime.getruntime()。可用处理器());我们可以通过配置pollerThreadCount对其进行自定义。

接受者用于接受新的连接。默认值为1。我们可以通过配置acceptorThreadCount对其进行自定义。

Request Process

Acceptor

Tomcat9请求处理流程与启动部署过程的示例分析

启动后,接受者将在ServerSocketChannel.accept()中阻止;方法,该方法在新连接到达时返回一个SocketChannel。

配置完套接字后,将套接字打包到NioChannel中,并将其注册到Poller。其价值在于,我们在开始时启动了许多轮询器线程,当注册时,连接被公平地分配给每个轮询器。NioEndpoint维护一组轮询器。当一个连接被分配给轮询器[index]时,下一个连接将被分配给轮询器[(index 1)% poller . length]。

addEvent()方法将套接字添加到此轮询器的轮询中。

nt 队列中。到此 Acceptor 的任务就完成了。

Poller

Tomcat9请求处理流程与启动部署过程的示例分析

  1. selector.select(1000)。当 Poller 启动后因为 selector 中并没有已注册的 Channel,所以当执行到该方法时只能阻塞。所有的 Poller 共用一个 Selector,其实现类是 sun.nio.ch.EPollSelectorImpl

  2. events() 方法会将通过 addEvent() 方法添加到事件队列中的 Socket 注册到 EPollSelectorImpl,当 Socket 可读时,Poller 才对其进行处理

  3. createSocketProcessor() 方法将 Socket 封装到 SocketProcessor 中,SocketProcessor 实现了 Runnable 接口。worker 线程通过调用其 run() 方法来对 Socket 进行处理。

  4. execute(SocketProcessor) 方法将 SocketProcessor 提交到线程池,放入线程池的 workQueue 中。workQueue 是 BlockingQueue 的实例。到此 Poller 的任务就完成了。

Worker

Tomcat9请求处理流程与启动部署过程的示例分析

  • 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)。

  1. CoyoteAdapter 将 Rquest 提交给 Container 处理之前,并将 org.apache.coyote.Request 封装到 org.apache.catalina.connector.Request,传递给 Container 处理的 Request 是 org.apache.catalina.connector.Request。

  2. 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

Tomcat9请求处理流程与启动部署过程的示例分析

  • 需要注意的是,基本上每一个容器的 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

  1. allocate() 用来加载并初始化 Servlet,值的一提的是 Servlet 并不都是单例的,当 Servlet 实现了 SingleThreadModel 接口后,StandardWrapper 会维护一组 Servlet 实例,这是享元模式。当然了 SingleThreadModel在 Servlet 2.4 以后就弃用了。

  2. createFilterChain() 方法会从 StandardContext 中获取到所有的过滤器,然后将匹配 Request URL 的所有过滤器挑选出来添加到 filterChain 中。

  3. doFilter() 执行过滤链,当所有的过滤器都执行完毕后调用 Servlet 的 service() 方法。

以上是“Tomcat9请求处理流程与启动部署过程的示例分析”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/142790.html

(0)

相关推荐