Tomcat请求处理流程与源码浅析

这篇具有很好参考价值的文章主要介绍了Tomcat请求处理流程与源码浅析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

系列文章目录和关于我
Tomcat请求处理流程与源码浅析

一丶Connector

在tomcat中,Connector负责开启socket并且监听客户端请求,返回响应数据。

Tomcat请求处理流程与源码浅析

其中:

  • Endpoint:tomcat中没有这个接口,只有AbstractEndpoint,它负责启动线程来监听服务器端口,并且在接受到数据后交给Processor处理
  • Processor:Processor读取到客户端请求后按照请求地址映射到具体的容器进行处理,这个过程请求映射,Processor实现请求映射依赖于Mapper对象,在容器发生注册和注销的时候,MapperListener会监听到对应的事件,从而来变更Mapper中维护的请求映射信息。
  • ProtocolHandler:协议处理器,针对不同的IO方式(NIO,BIO等)和不同的协议(Http,AJP)具备不同的实现,ProtocolHandler包含一个Endpoint来开启端口监听,并且包含一个Processor用于按照协议读取数据并将请求交给容器处理。
  • Acceptor:Acceptor实现了Runnable接口,可以作为一个线程启动,使用Socket API监听指定端口,用于接收用户请求。
  • Poller:主要用于监测注册在原始 scoket 上的事件是否发生,Acceptor接受到请求后,会注册到Poller的队列中。

二丶NioEndpoint 初始化ServerSocketChannel

springboot内嵌tomcat,一般默认使用NioEndpoint,在NioEndpoint#start方法中,会触发NioEndpoint#bind

Tomcat请求处理流程与源码浅析

三丶NioEndpoint 启动Poller和Acceptor线程

NioEndpoint#start方法最后会触发Poller线程和Acceptor线程的启动

Tomcat请求处理流程与源码浅析

Tomcat请求处理流程与源码浅析

可以看到NioEndpoint内部的Poller,和Acceptor都是单独使用一个守护线程来运行。

四丶Acceptor接收请求

Tomcat请求处理流程与源码浅析

1.endpoint.countUpOrAwaitConnection()限制连接数

其内部使用LimitLatch#countUpOrAwait方法限制连接数,如果连接数达到了上限,那将挂起当前线程,也就是挂起Acceptor线程,从而导致无法有更多的请求连接上来,最大连接数默认为8*1024。

LimitLatch 内部持有一个AbstractQueuedSynchronizer,限制连接数将调用其acquireSharedInterruptibly(1),然后会调用到AQS的tryAcquireShared,其内部使用AtomicLong来进行连接的计数。

Tomcat请求处理流程与源码浅析

2.NioEndpoint#serverSocketAccept 接收Socket连接

Tomcat请求处理流程与源码浅析

由于NioEndpoint前面调用了ServerSocketChannel#configureBlocking(true),所以serverSock#accept,在没有连接上来时,不会立马返回null,而是阻塞直到连接来到。

3.NioEndpoint#setSocketOptions将SocketChannel注册到Poller

Tomcat请求处理流程与源码浅析

在Acceptor线程接收到SocketChannel后,会调用Poller#register方法进行注册,Acceptor只负责接受请求,请求后续的处理由Poller线程负责

Tomcat请求处理流程与源码浅析

Tomcat请求处理流程与源码浅析

最终请求被包装为PollerEvent丢到Poller的事件队列SynchronizedQueue中,SynchronizedQueue使用synchronized保证线程安全。

wakeupCounter 是AtomicLong类型,Acceptor接受到请求,将请求封装为PollerEvent后会调用wakeupCounter#incrementAndGet方法,进行+1操作

Poller在使用Selector,进行IO多路复用的时候,会进行如下操作

Tomcat请求处理流程与源码浅析

可以看到,如果wakeupCounter大于0,Poller会调用 selector.selectNow()(非阻塞立马返回),反之调用selector.select(selectorTimeout)(超时并阻塞)。

也就说Acceptor接受到请求越多,wakeupCounter越大,越会让Poller调用selector.selectNow()减少阻塞,从而让Poller更快的检查事件是否就绪,从而让请求更及时的被处理。

五丶Poller处理事件

1.events方法查看事件队列是否具备事件

上面我们说到Acceptor在建立连接后,将SocketChannel包装成NioSocketWrapper塞到了Poller的事件队列中。而Poller线程则会一直轮询这个队列进行事件的获取

Tomcat请求处理流程与源码浅析

2.Poller 使用Selector进行select

Tomcat请求处理流程与源码浅析

通过Selector获取获取当前就绪的IO,keyCount记录就绪数目。

3.Poller 处理就绪IO

Tomcat请求处理流程与源码浅析

processKey会调用到processSocket,最终使用tomcat线程池中的线程进行异步处理

Tomcat请求处理流程与源码浅析

最终会找到Processor进行处理(默认使用缓存的,避免重复new对象,频繁gc,如果缓存没有那么使用ProtocolHandler 创建出一个),这里的Processor就是Http11Processor

然后根据事件类型进行不同的处理,如果是读事件那么会调用Http11Processor#service进行处理,然后会继续交给CoyoteAdapter调用其service进行处理。

六丶CoyoteAdapter处理请求

1.使用Mapper找到请求对应的Host,Context,Wrapper

Tomcat请求处理流程与源码浅析

下图是的模型,如果使用了SpringMVC,这里的Wrapper会存在DispatchServlet

Tomcat请求处理流程与源码浅析

如下是Mapper找到的MappingData

Tomcat请求处理流程与源码浅析

2.Pipeline执行

Tomcat请求处理流程与源码浅析

上面说到,Mapper会找到当前请求所属的host,context和对应的Wrapper,紧接着会进行Pipeline的执行。

为了增强扩展性,tomcat定义了Pipeline(管道)和Valve(阀),Pipeline使用职责链的方式串联多个Valve——来自客户端的请求如同流水一样流淌在管道中,受到每一个阀的作用。

Tomcat请求处理流程与源码浅析

Pipeline中维护了基础的Valve,始终位于Pipeline末端,通过Pipeline#addValve添加的Valve违约基础的Valve之前。

在Tomcat中Engine,Host,Context,Wrapper都有对应的Valve实现,同时维护了一个Pipeline,从而让我们可以对请求的处理进行扩展。

下面是比较重要的Valve

  • StandardEngineValve :Engine对应的Valve,负责请求是否通过mapper找到了对应的Host,并触发Host对应的ValveTomcat请求处理流程与源码浅析

  • ErrorReportValve: 错误报告Valve让后续的Valve继续执行,如果执行出现错误那么会刷新响应流,让客户端收到响应Tomcat请求处理流程与源码浅析

  • StandardHostValve:Host对应的Valve,如果请求没有匹配的context返回404,反之调用Context对应的ValveTomcat请求处理流程与源码浅析

  • StandardContextValve:Context对应的Valve,如果请求路径以/META-INF/,或者/WEB-INF/开头,会直接返回404,反之继续调用Wrapper对应的

  • StandardWrapperValve:Wrapper对应的Valve,会负责组装Servlet和Filter,并执行FilterChain#doFilter方法

    Tomcat请求处理流程与源码浅析

    Filter的匹配主要通过DispatchType和Filter设置的路径,Tomcat请求处理流程与源码浅析

    在SpringBoot项目中可以使用FilterRegistrationBean#setDispatcherTypes,和addUrlPatterns进行指定。

3.FilterChain执行

在Tomcat中ApplicationFilterChain实现了Java Servlet规范中的FilterChain。

Tomcat请求处理流程与源码浅析

其中使用ApplicationFilterConfig是对FilterConfig的实现,内部持有一个Filter。

ApplicationFilterChain包含多个ApplicationFilterConfig,使用数组和pos属性记录当前执行到第几个Filter

Tomcat请求处理流程与源码浅析

Filter都执行结束后,将执行Servlet#service方法

在SpringMVC项目中,会调用到DispatcherServlet#service,最终调用到Controller。文章来源地址https://www.toymoban.com/news/detail-462280.html

到了这里,关于Tomcat请求处理流程与源码浅析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 浅析Redis①:命令处理核心源码分析(上)

    写在前面 Redis作为我们日常工作中最常使用的缓存数据库,其重要性不言而喻,作为普调开发者,我们在日常开发中使用Redis,主要聚焦于Redis的基层数据结构的命令使用,很少会有人对Redis的内部实现机制进行了解,对于我而言,也是如此,但一直以来,我对于Redis的内部实

    2024年01月19日
    浏览(62)
  • Tomcat处理请求的全过程

    在Tomcat处理客户端请求的过程中,这里面有三个组件概念,他们都是线程,分别负责不同的职责。 (必须记清楚这三个线程组件) Acceptor 一个普通线程任务,用于接收新连接,并将新连接封装,选择一个 Poller 将新连接添加到 Poller 的事件队列中。 Poller 一个线程任务,用于

    2024年01月20日
    浏览(34)
  • DevOps系列文章之 Dockerfile 使用流程

    主要步骤: Step1、准备项目应用程序包 Step2、编写Dockerfile及启动脚本 Step3、docker build 构建镜像 Step4、docker run 启动容器 Step5、docker exec 进入容器进行验证 Step6、镜像的导入导出 Step7、提交容器生成新镜像 Step1、准备项目应用程序包 根据项目需要,将应用程序包、Nginx配置文件

    2024年02月16日
    浏览(34)
  • GPT 告诉你请求到达 Tomcat 是怎么处理的

    tomcat如何监听请求到达 没有SpringMVC,tomcat 如何处理请求 Tomcat 线程池的作用是什么 如何配置tomcat 线程池 tomcat 线程池的主要任务是处理连接请求 tomcat线程池是怎么实现的 到这里可以看出来,tomcat线程池的实现方式也是通过ThreadPoolExecutor 实现 如何根据请求url 找到对应的serv

    2024年02月02日
    浏览(34)
  • SpringBoot源码学习4——SpringBoot内嵌Tomcat启动流程源码分析

    系列文章目录和关于我 我在初学spring的时候,很懵逼,因为整个项目中不存在main方法,让我有点摸不着头脑。那时候我知道有个东西叫tomcat是它监听了端口,解析了协议调到了我的servlet。 在我初学SpringBoot的时候,很懵逼,有main方法了,但是tomcat在哪里呢,又是如何启动起

    2024年02月04日
    浏览(42)
  • SpringBoot配置外部Tomcat项目启动流程源码分析

    SpringBoot应用默认以Jar包方式并且使用内置Servlet容器(默认Tomcat),该种方式虽然简单但是默认不支持JSP并且优化容器比较复杂。故而我们可以使用习惯的外置Tomcat方式并将项目打War包。 ① 同样使用Spring Initializer方式创建项目 ② 打包方式选择\\\"war\\\" ③ 选择添加的模块 ④ 创建的

    2024年02月04日
    浏览(37)
  • 【Tomcat】Tomcat的实现,tomcat内部是怎么实现的,它是怎么做到对Servlet请求的处理的。

    让你想手写一个tomcat容器 能做到吗 Tomcat是Servlet容器,这句话真的是精髓,但有怎么理解呢? Tomcat的代码实现,原理 尝试自己手写一份tomcat服务,类似tomcat的功能。 tomcat是servlet容器。所以我们自己写的tomcat也要满足这个功能,能接受处理servlet请求。 这一段的代码还是很经

    2024年02月09日
    浏览(33)
  • 极验系列文章一:极验三代 极验验证码整体流程分析

    作为一位js逆向爱好者,写本篇文章在于纯技术分析。无任何不良商业目的。旨在提高大家的网络安全意识,共同维护网络安全环境!请不要做任何有损国家或其他集体或个人的事情, 否者后果自负!本文如有任何侵权行为,请马上联系作者,立马删除。 目标地址:aHR0cHM6

    2024年02月14日
    浏览(33)
  • Spring MVC请求处理流程和九大组件

    需求:前端浏览器请求url: http://localhost:8080/demo/handle01,前端⻚⾯显示后台服务器的时间 开发过程 配置DispatcherServlet前端控制器 开发处理具体业务逻辑的Handler(@Controller、@RequestMapping) xml配置⽂件配置controller扫描,配置springmvc三⼤件 将xml⽂件路径告诉springmvc(DispatcherSer

    2024年02月07日
    浏览(42)
  • Flutter网络请求框架Dio源码分析以及封装(一)--请求流程分析

    利用flutter开发app也已经有些时间了,这个过程中最多接触到的就是网络请求相关的代码。自己目前项目中使用的是现在市面上最流行的网络请求库-dio,相对于flutter自带的HttpClient来说,dio使用起来更简单,功能更强大,支持全局配置、Restful API、FormData、拦截器、 请求取消、

    2024年02月09日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包