首页 > 编程语言 >Tomcat请求处理流程与源码浅析

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

时间:2023-05-28 17:55:58浏览次数:55  
标签:调用 请求 Tomcat Valve 源码 线程 Poller 浅析 Acceptor

系列文章目录和关于我
image-20230507214918965

一丶Connector

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

image-20230521211759461

其中:

  • 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

image-20230521214539181

三丶NioEndpoint 启动Poller和Acceptor线程

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

image-20230521215101571

image-20230521215243031

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

四丶Acceptor接收请求

image-20230521220055751

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

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

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

image-20230521221136584

2.NioEndpoint#serverSocketAccept 接收Socket连接

image-20230521221800829

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

3.NioEndpoint#setSocketOptions将SocketChannel注册到Poller

image-20230521224050992

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

image-20230521224257316

image-20230521224401100

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

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

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

image-20230521225002993

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

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

五丶Poller处理事件

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

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

image-20230528152708481

2.Poller 使用Selector进行select

image-20230528153510951

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

3.Poller 处理就绪IO

image-20230528154651828

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

image-20230528155459420

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

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

六丶CoyoteAdapter处理请求

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

image-20230528164457609

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

image-20230515003153142

如下是Mapper找到的MappingData

image-20230528164322639

2.Pipeline执行

image-20230528170245899

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

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

image-20230507184619665

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

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

下面是比较重要的Valve

  • StandardEngineValve :Engine对应的Valve,负责请求是否通过mapper找到了对应的Host,并触发Host对应的Valveimage-20230528170655504

  • ErrorReportValve: 错误报告Valve让后续的Valve继续执行,如果执行出现错误那么会刷新响应流,让客户端收到响应image-20230528171000836

  • StandardHostValve:Host对应的Valve,如果请求没有匹配的context返回404,反之调用Context对应的Valveimage-20230528171220823

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

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

    image-20230528171752416

    Filter的匹配主要通过DispatchType和Filter设置的路径,image-20230528172344294

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

3.FilterChain执行

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

image-20230528172912949

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

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

image-20230528173109162

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

在SpringMVC项目中,会调用到DispatcherServlet#service,最终调用到Controller。

标签:调用,请求,Tomcat,Valve,源码,线程,Poller,浅析,Acceptor
From: https://www.cnblogs.com/cuzzz/p/17438563.html

相关文章

  • 202305281631-《远程Linux服务器——安装tomcat8、jdk1.8、mysql5——mysql workerben
    bash已连接的上,但workerbench连不上,提示:1.FailedtoConnecttoMySQLat11.11.11.111:[email protected]'11.11.11.111'isnotallowedtoconnecttothisMySQLserver解决办法(为什么,我也不知道):1.登录mysql,一次执......
  • 202305280952-《远程Linux服务器——安装tomcat8、jdk1.8、mysql5——mysql启动报错》
    在bash执行"systemctlstartmysqld"   提示:“Jobformysqld.servicefailedbecausethecontrolprocessexitedwitherrorcode.See"systemctlstatusmysqld.service"and"journalctl-xe"fordetails.”   /var/lib/mysql权......
  • coreutils test 源码分析
    Test的代码中主要解析如下语法,当然使用的时候也可以参考如下语法进行语句的编写/*test(1)acceptsthefollowinggrammar:oexpr::=aexpr|aexpr"-o"oexpr;aexpr::=nexpr|nexpr"-a"aexpr;nexpr::=primary|"!"primaryprimary::=un......
  • 源码编译安装php7.4
    1.下载解压PHP7.4php源码包下载地址各版本源码包https://www.php.net/releases/解压缩tar-zxvf命令tar-zxvfphp-7.4.33.tar.gz2.安装PHP+FPM进入解压后的PHP源码目录php-7.4.33cdphp-7.4.33执行./configure指令./configure--with-openssl--with-cur......
  • JAVA的springboot私人健身与教练预约管理系统、健身房管理系统,附源码+数据库+lw文档+P
    1、项目介绍任何系统都要遵循系统设计的基本流程,本系统也不例外,同样需要经过市场调研,需求分析,概要设计,详细设计,编码,测试这些步骤,基于java技术、springboot框架、B/S机构、Mysql数据库设计并实现了私人健身与教练预约管理系统。系统主要包括首页,个人中心,用户管理,教练管理,健身项目......
  • 互联网医院系统源码解析:数字化医疗时代的新起点
    互联网医院系统源码作为互联网医疗的核心技术之一,对于医疗行业的智能化升级和服务质量提升有着重要的作用。下文小编将会对智慧医疗、互联网医院系统源码进行深度讲解,与大家一同探讨数字医疗的新方案。 一、概念解答简单来说,互联网医院系统源码就是搭建智慧医疗互联网医院的“根基......
  • 基于JAVA的sprinboot+vue车辆充电桩,附源码+数据库+论文+PPT
    1、项目介绍利用springboot、Java、idea和mysql数据库等知识点,结合相关设计模式、以及软件工程的相关知识,设计一个车辆充电桩管理系统,来进行记录用户的信息,以及系统信息的增删改查的功能,根据实现需求,系统需完成这些基本功能:(1)系统合理显示系统首页界面,管理员界面,用户界面和维修员......
  • Spring源码分析-BeanDefination加载
    ConfigurationClassPostProcessor解析配置类中有两类集合,一类是配置类、另一类是所有已解析的bd从已有bd中过滤配置类​ candidateNames:保存已被解析出来的所有待解析的bd名​ configCandidates:candidateNames经过过滤的所有待解析的配置类bd​ 过滤条件:​ 检查BeanDefi......
  • WPF入门实例 WPF完整例子 WPF DEMO WPF学习完整例子 WPF实战例子 WPF sql实例应用 WPF
    WPF和WinForms都是用于创建Windows桌面应用程序的开发框架,它们有一些相似之处,但也有很多不同之处。在开发速度方面,这取决于具体情况。如果您熟悉WinForms开发并且正在开发简单的界面应用程序,则可能会比使用WPF更快速地完成任务。然而,在设计和实现复杂的用户界面时,WPF可......
  • java基于springboot+vue时间管理系统、日记管理系统,附源码+数据库+lw文档+PPT
    1、项目介绍本次设计任务是要设计一个时间管理系统,通过这个系统能够满足时间管理的管理功能。系统的主要功能包括首页,个人中心,系统公告管理,用户管理,时间分类管理,事件数据管理,目标数据管理,用户日记管理等功能。管理员可以根据系统给定的账号进行登录,登录后可以进入时间管理系统,对......