如何实现Tomcat请求处理

发布时间:2022-01-12 17:31:41 作者:柒染
来源:亿速云 阅读:203

这篇文章跟大家分析一下“如何实现Tomcat请求处理”。内容详细易懂,对“如何实现Tomcat请求处理”感兴趣的朋友可以跟着小编的思路慢慢深入来阅读一下,希望阅读后能够对大家有所帮助。下面跟着小编一起深入学习“如何实现Tomcat请求处理”的知识吧。

很多东西在时序图中体现的已经非常清楚了,没有必要再一步一步的作介绍,所以本文以图为主,然后对部分内容加以简单解释。

绘制图形使用的工具是 PlantUML + Visual Studio Code + PlantUML Extension

下面对 Tomcat 的介绍以 Tomcat-9.0.0.M22 为标准。

Tomcat-9.0.0.M22 是 Tomcat 目前最新的版本,但尚未发布,它实现了 Servlet4.0 及 JSP2.3 并提供了很多新特性,需要  1.8 及以上的 JDK 支持等等。

Overview

如何实现Tomcat请求处理

Connector 启动以后会启动一组线程用于不同阶段的请求处理过程。

  1. Acceptor 线程组。用于接受新连接,并将新连接封装一下,选择一个 Poller 将新连接添加到 Poller 的事件队列中。

  2. Poller 线程组。用于监听 Socket 事件,当 Socket 可读或可写等等时,将 Socket 封装一下添加到 worker  线程池的任务队列中。

  3. worker 线程组。用于对请求进行处理,包括分析请求报文并创建 Request 对象,调用容器的 pipeline 进行处理。

Acceptor、Poller、worker 所在的 ThreadPoolExecutor 都维护在 NioEndpoint 中。

Connector Init and Start

如何实现Tomcat请求处理
  1. initServerSocket(),通过 ServerSocketChannel.open() 打开一个 ServerSocket,默认绑定到 8080  端口,默认的连接等待队列长度是 100, 当超过 100 个时会拒绝服务。我们可以通过配置 conf/server.xml 中 Connector 的  acceptCount 属性对其进行定制。

  2. createExecutor() 用于创建 Worker 线程池。默认会启动 10 个 Worker 线程,Tomcat 处理请求过程中,Woker  最多不超过 200 个。我们可以通过配置 conf/server.xml 中 Connector 的 minSpareThreads 和 maxThreads  对这两个属性进行定制。

  3. Pollor 用于检测已就绪的 Socket。默认最多不超过 2  个,Math.min(2,Runtime.getRuntime().availableProcessors());。我们可以通过配置  pollerThreadCount 来定制。

  4. Acceptor 用于接受新连接。默认是 1 个。我们可以通过配置 acceptorThreadCount 对其进行定制。

Request Process

Acceptor

如何实现Tomcat请求处理
  1. Acceptor 在启动后会阻塞在 ServerSocketChannel.accept(); 方法处,当有新连接到达时,该方法返回一个  SocketChannel。

  2. 配置完 Socket 以后将 Socket 封装到 NioChannel 中,并注册到 Poller,值的一提的是,我们一开始就启动了多个 Poller  线程,注册的时候,连接是公平的分配到每个 Poller 的。NioEndpoint 维护了一个 Poller 数组,当一个连接分配给  pollers[index] 时,下一个连接就会分配给 pollers[(index+1)%pollers.length].

  3. addEvent() 方法会将 Socket 添加到该 Poller 的 PollerEvent 队列中。到此 Acceptor 的任务就完成了。

Poller

如何实现Tomcat请求处理
  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

如何实现Tomcat请求处理
  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() 都是。

Container

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

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

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

关于如何实现Tomcat请求处理就分享到这里啦,希望上述内容能够让大家有所提升。如果想要学习更多知识,请大家多多留意小编的更新。谢谢大家关注一下亿速云网站!

推荐阅读:
  1. 如何异步请求处理函数
  2. 6张时序图,谈谈Tomcat请求处理流程

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

tomcat

上一篇:python怎么实现随机森林

下一篇:python机器学习的程序怎么写

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》