关于springboot内置tomcat最大请求数配置的一些问题

news/2024/9/20 9:00:33/ 标签: spring boot, tomcat, 后端

前言

springboot内置了tomcat。那么一个springboot web应用,最大的请求链接数是多少呢?很早以前就知道这个是有个配置,需要的时候,百度一下即可。但,事实并非如此,有几个问题我想大多数人还真不知道。比如:

  • 为什么会有最大连接数和等待队列两个配置:要限制最大链接,用一个最大连接数限制即可,搞个等待队列有什么用呢?(我看网上有说,就像是餐厅有在餐厅里等待上菜的(最大链接数),也有在外坐小板凳排队的(等待队列),但,餐厅这么设计,可以说是由于实际场地等因素,那程序呢?它考虑的是什么?)
  • 有两个应用A、B,A调用B的一个接口,A在http请求方法的开始和结尾记录了时间,相减得到值是20s,B方法在controller方法的开头和结尾(或者AOP拦截)也记录了时间是10s,如果认为接口15s以内都是正常的,那么B就会认为自己的接口正常,A认为B的接口不正常。那么这差的10s问题出在哪里?

说明:

  1. 有些结论叙述不太准,但是这并不重要,理解所表达的意思即可,不要纠结一个答案;
  2. 有些配置的默认值,或者结论现象和网上其他说法不同,不必怀疑,可能大家都是对的,我们的环境不同罢了

正文

关于spirngboot内置tomcat的最大请求数,大体有如下四个配置:(后续配置中,如不特殊说明,都是按照这个参数值来进行验证)

#最少的工作线程数,默认大小是10
server.tomcat.threads.min-spare=1
#最多的工作线程数,默认大小是200
server.tomcat.threads.max=2
#最大连接数,默认大小是8192。表示Tomcat可以处理的最大请求数量,超过8192的请求就会被放入到等待队列。
server.tomcat.max-connections=2
#等待队列的长度,默认大小是100。
server.tomcat.accept-count=4

结论

先直接上结论,后续一一用代码来实际论证:

  1. 最小工作线程数server.tomcat.threads.min-spare是一个优化配置,应用启动就会创建相应数目的线程(不管有没有请求),这些线程是不会被销毁的,而server.tomcat.threads.max是在请求的任务数多的时候,会临时创建的线程,之后这些线程会被销毁;
  2. 最大可接受的请求数为:server.tomcat.max-connections + server.tomcat.accept-count,超过该数目会拒绝请求;
  3. 最多能同时工作的线程数是:server.tomcat.threads.max
  4. 如果配置server.tomcat.max-connections 小于server.tomcat.threads.max,那么实际中创建的任务线程数应该是:server.tomcat.max-connections
  5. 最大连接数中的请求没有处理完之前,是不会处理等待队列中的请求的;
  6. 假如把最大连接数和等待队列都看作容器:那么
    • 并非是要等最大链接数中的链接,全部处理完了,才会处理等待队列中的链接,而是最大链接容器中,有空位了,等待队列中就会有个链接进入最大链接容器,从而又可以接受一个新的链接了(debug源码发现:其实接受最大链接的池子是一个无限队列,但是通过server.tomcat.max-connections来控制这个最多能容纳的链接,当等于max-connections之后,新的链接就会进入等待队列,判断是否拒绝链接,是判断当前请求中,server.tomcat.accept-count的值是否大于等于配置值,如果是就拒绝链接)
    • 等待队列的存在是有意义的,特别是在异步请求

论证

这里我准备了一个接口,不考虑其他代码(如拦截器、过滤器之类的)的执行耗时,就认为这个接口的耗时时间为10s:

@GetMapping("/test10")
public String test10() throws InterruptedException {log.info("当前线程test10:{}.", Thread.currentThread().getName());Thread.sleep(10000);return "test10s";
}

应用启动就会创建min-spare个线程

依次将server.tomcat.threads.min-spare设置为1、2、3,会发现项目启动后,就会创建对应多个数目的线程数(不要将该数值设置的大于server.tomcat.threads.max),当链接超过了这个最小的线程数之后,就会再创建线程,但是不会超过最大链接数,这些线程最终会被销毁(项目启动时创建的server.tomcat.threads.min-spare的线程却不会被销毁)

image.png

image.png

image.png

tomcatmaxconnections__servertomcatacceptcount_54">最大可接受请求数:server.tomcat.max-connections + server.tomcat.accept-count

现在配置的server.tomcat.max-connections + server.tomcat.accept-count 为7,那么发起7个请求,就应该有6个请求得到正常响应,一个请求被拒绝:

image.png

tomcatthreadsmax_59">最多能同时工作的线程数是:server.tomcat.threads.max

同样,用上面的验证结果,看响应时间:

image.png

我配置的server.tomcat.threads.max为2,意味着同时有两个线程会执行请求。那么,接口耗时10s,每两个线程的响应时间是相同的,两两之间相差10秒。

想一下开头说的:A、B两应用接口调用有10s的时间对不上,也许有一种可能就是这里:从接口打印的时间来看,是10秒,但是实际的响应却是10s、20s、30s。

由此可见:有些项目所谓的接口响应时间的记录,其实仅仅是记录的业务代码的执行时间。对于请求方而言,并非接口的响应时间。知道这个,对于分析问题,又多了一种思路了。

tomcatmaxconnections_servertomcatthreadsmaxservertomcatmaxconnections_70">如果配置server.tomcat.max-connections 小于server.tomcat.threads.max,那么实际中创建的任务线程数应该是:server.tomcat.max-connections

这种配置法,在实际中是不存在的,我想,应该不会有人这么干吧!!!

server.tomcat.threads.min-spare=1
server.tomcat.threads.max=3
server.tomcat.max-connections=2
server.tomcat.accept-count=4

依然是7个请求并发,结果一个失败,6个成功,耗时30秒:

image.png

看这个图,时间依旧是两两一组,说明虽然允许最多创建3个任务线程,但是实际最大链接有2个,那么也认为只有两个任务要执行,而不会管等待队列中的任务。只有等最大链接池中的任务有执行完的了,才会让等待队列中的任务进来。
如果把server.tomcat.threads.min-spare设置为3,结果也是一样的。

最大连接数中的请求没有处理完之前,是不会处理等待队列中的请求的

这个结论是在其他地方看到的,当时一直不理解:假如最大链接数中有10个请求,等待有2个,那么必须要等到这10个请求全部完成了,才会处理等待队列的两个吗?其实,这句话的意思应该是,创建出的线程只会处理最大连接数中的请求,当有一个请求完了之后,才会让等待队列中的请求进来,然后然后又被任务线程处理。即便有空余的任务线程,也不会处理等待队列中的请求。在:

如果配置server.tomcat.max-connections 小于server.tomcat.threads.max,那么实际中创建的任务线程数应该是:server.tomcat.max-connections

已经论证了。

等待队列存在的作用

虽然之前也有说了,最大连接数中的请求没有处理完之前,是不会处理等待队列中的请求的,但这个作用意义不大,毕竟在实际中,不会有人配置工作线程数小于最大线程数。
所以,从以上现象中看,这个等待队列的意义不大(从我的测试结果看,这个确实没有啥意义,但是如果看源码,它还是有作用的,但我认为按照官方指导数来配置就可以了,理解它的作用比较抽象),除非————使用异步请求

之前的接口,都是同步请求的:工作线程从最大链接容器中拿取一个人请求处理,处理完之后,再拿取下一个,它所针对的是最大链接,和等待队列没有关系,但等待队列看到最大链接中有空位了,就安排它的一个链接请求去补位,所以,从这里看它的存在意义不大。

但如果是异步请求中,这个等待队列就有意义了:如之前所说,工作线程只管最大请求链接中的请求。那么如果我允许项目的最大链接说是10,只有一个参数控制这个值的话,在异步线程中几乎可以认为会同时处理10个请求,但有了等待队列,则可以控制同时处理的请求数了。描述的不是很准确,直接看结果:增加一个异步请求接口和之前的同步请求逻辑一样,从客户端的角度看,这两个接口都是耗时10s:

@GetMapping("/testCallAble")
public Callable<String> testCallAble(){return () -> {log.info("当前线程:{}.", Thread.currentThread().getName());Thread.sleep(10000);return "hello";};
}

使用如下配置参数,依次请求两个接口:7个并发请求:

server.tomcat.threads.min-spare=1
server.tomcat.threads.max=2
server.tomcat.max-connections=4
server.tomcat.accept-count=2

异步请求结果:1个请求失败,总耗时20秒:有4个请求(server.tomcat.max-connections的值)是同一时间返回的:说明任务线程由于异步请求,它空闲出来之后会处理最大链接数中的其他请求,但是不会处理等待队列中的请求。如果没有等待队列,那么就会造成这个异步线程会一下处理6(server.tomcat.max-connections+server.tomcat.accept-count)个请求链接的业务方法,这个时候可能服务器没有足够的资源。
image.png

同步请求结果:1个请求失败,总耗时30秒:每两个请求的响应时间是相同的:
image.png

通过以上例子以及之前的例子,对于这个等待队列,应该有了个较为清晰且模糊的认识了吧。哈哈!!!


http://www.ppmy.cn/news/1451946.html

相关文章

基于Sping Boot集成的websocket实现聊天室

Spring Boot整合WebSocket实现聊天室 Spring Boot 提供了 Websocket 组件 spring-boot-starter-websocket&#xff0c;用来支持在 Spring Boot环境下对Websocket 的使用。 下面我们就以多人在线聊天室为例&#xff0c;演示 Spring Boot 是如何整合Websocket 实现服务端消息推…

python(abi)是什么,有什么作用呢

python(abi) 是一个特殊的提供项&#xff0c;用于指定软件包所支持的Python ABI&#xff08;Application Binary Interface&#xff09;版本。 Python ABI是一种约定&#xff0c;用于定义Python解释器和扩展模块之间的二进制接口。它确保了不同版本的Python解释器和扩展模块之…

如何使用提示测试为LLMs构建单元测试?

原文地址&#xff1a;how-to-build-unit-tests-for-llms-using-prompt-testing 确保您的人工智能交付&#xff1a;快速测试完美生成应用程序的基本指南 2024 年 4 月 26 日 如果你曾经编写过软件&#xff0c;你就会知道测试是开发过程中必不可少的一部分。特别是单元测试&#…

JavaWeb--1.Servlet

Servlet&#xff08;基础&#xff09; 1、配置依赖&#xff1a; ​ 在pom.xml文件中加入相关依赖 <dependencies><dependency><groupId>jakarta.servlet</groupId><artifactId>jakarta.servlet-api</artifactId><version>5.0.0&l…

KAN网络认识

首先&#xff0c;这是一个基于柯尔莫哥洛夫-阿诺德表示定理的网络。这个定理指出如果函数f是定义在有界域上的多变量连续函数&#xff08;即最终要拟合的非线性函数是连续的&#xff09;&#xff0c;那么该函数就可以表示为多个单变量、加法连续函数的有线组合。 对于机器学习…

手撸Mybatis(三)——收敛SQL操作到SqlSession

本专栏的源码&#xff1a;https://gitee.com/dhi-chen-xiaoyang/yang-mybatis。 引言 在上一章中&#xff0c;我们实现了读取mapper配置并构造相关的mapper代理对象&#xff0c;读取mapper.xml文件中的sql信息等操作&#xff0c;现在&#xff0c;在上一章的基础上&#xff0c…

【热门话题】Chrome 插件研发详解:从入门到实践

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 Chrome 插件研发详解&#xff1a;从入门到实践一、引言二、Chrome 插件基础概念…

嵌入式物联网系统软硬件基础知识大全(2)

接口技术 1. Flash存储器 (1)Flash存储器是一种非易失性存储器,根据结构的不同可以将其分为NOR Flash和NAND Flash两种。 (2)Flash存储器的特点: A、区块结构:在物理上分成若干个区块,区块之间相互独立。 B、先擦后写:Flash的写操作只能将数据位从1写成0,不能从…

写自己的c库----小话c语言(19)

Q&#xff1a; 对于c代码&#xff0c;经常可能被c代码使用&#xff0c;所以经常需要使用extern "C"语句&#xff0c;老是写这段代码真是很烦人&#xff0c;有什么好的方法&#xff1f; A&#xff1a; 对于重复代码来说&#xff0c;宏无疑是个很好的方法。 #if defin…

spring高级篇(八)

本篇对Spring MVC 的执行流程做一个简单总结 MVC执行流程总结 当浏览器发送一个请求&#xff0c;例如http://localhost:8080/hello&#xff0c;请求到达服务器后&#xff0c;一般会进行如下操作&#xff1a; 1、首先会经过DispatcherServlet&#xff0c;默认映射路径为 /&…

global IoT SIM解决方案

有任何关于GSMA\IOT\eSIM\RSP\业务应用场景相关的问题&#xff0c;欢迎W: xiangcunge59 一起讨论, 共同进步 (加的时候请注明: 来自CSDN-iot). Onomondo提供的全球IoT SIM卡解决方案具有以下特点和优势&#xff1a; 1. **单一全球配置文件**&#xff1a;Onomondo的SIM卡拥…

Apache POI 在java中处理excel

介绍: Apache POI 是一个处理Miscrosoft Office各种文件格式的开源项目。简单来说就是&#xff0c;我们可以使用 POI 在 Java 程序中对Miscrosoft Office各种文件进行读写操作。 一般情况下&#xff0c;POI 都是用于操作 Excel 文件。 如何使用: 1.maven坐标引入 <depend…

【RabbitMQ 一】RabbitMQ简介、消息中间件、MQ的作用

RabbitMQ简介 很多介绍RabbitMQ的地方&#xff0c;上来就说这是一种消息中间件&#xff08;Message Queue Middleware&#xff09;。对于一些新手或者初级开发人员&#xff0c;“中间件”的概念并不是很清晰。那么什么是中间件呢&#xff1f; 1.什么是中间件 个人以为&#…

Spark SQL编程初级实践

参考链接 Spark编程: Spark SQL基本操作 2020.11.01_df.agg("age"->"avg")-CSDN博客 RDD编程初级实践-CSDN博客 Spark和Hadoop的安装-CSDN博客 1. Spark SQL基本操作 { "id":1 , "name":" Ella" , "age":…

头歌实践教学平台:投影变换v2.0

第4关&#xff1a;视口变换与三视图 一. 任务描述 1. 本关任务 (1) 理解投影变换的方法; (2) 将main函数中的空白部分补充完整。 2. 输入 (1) 代码将自动输入一个边长为1的obj正方体模型&#xff0c;具体模型如下图&#xff1a; (2) 代码自动将模型投影到二维平面&#xf…

在M1芯片安装鸿蒙闪退解决方法

在M1芯片安装鸿蒙闪退解决方法 前言下载鸿蒙系统安装完成后&#xff0c;在M1 Macos14上打开闪退解决办法接下来就是按照提示一步一步安装。 前言 重新安装macos系统后&#xff0c;再次下载鸿蒙开发软件&#xff0c;竟然发现打不开。 下载鸿蒙系统 下载地址&#xff1a;http…

HTTP协议 --中

http状态码 当浏览者访问一个网页时&#xff0c;浏览者的浏览器会向网页所在服务器发出请求。当浏览器接收并显示网页前&#xff0c;此网页所在的服务器会返回一个包含HTTP 状态码的信息头&#xff08; server header &#xff09;用以响应浏览器的请求。 HTTP 状态码的英文为…

UDP_INTRODUCTION_03:介绍 - 挂起的监听调用

测试目的&#xff1a; 验证当数据报到达一个没有挂起监听&#xff08;LISTEN&#xff09;调用的UDP端口时&#xff0c;UDP是否应该发送ICMP端口不可达&#xff08;Port Unreachable&#xff09;消息。 描述&#xff1a; 本测试用例旨在确保当数据报发送到DUT上一个未被监听的…

esp32-cam 2. python opencv 拉取摄像头内容

0. 环境 - win10 python3 - pycharm - esp32-cam http://192.168.4.1 1. 创建工程 File -> Create Project -> -> Location: E:\Workspaces\PycharmProjects\esp32cam_opencv -> Create 2. opencv hello 2.1 添加脚本 File -> New -> Python f…

1.3 Java全栈开发前端+后端(全栈工程师进阶之路)-前置课程CSS,看这一篇就够了

前面我们已经讲了前端三剑客中的html和JavaScript&#xff0c;那么现在我们来看一下CSS CSS核心 0、清除默认样式 * {/* 清除默认样式 */margin: 0;padding: 0; } 1、尺寸操作-内外边距 .box {/* 尺寸操作 *//* 宽度 */width: 500px ; /* 高度 */height: 280px;/* 边框 *…