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

news2024/11/19 19:39:58

前言

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

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

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

image.png

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

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

image.png

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

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

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

如果配置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.coloradmin.cn/o/1629308.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

机械图纸管理系统,如何选择适合的机械图纸管理系统?

机械图纸管理系统是一种专门用于管理和跟踪机械制造过程中的图纸、设计文件和相关信息的软件系统。例如&#xff1a;彩虹图纸管理系统&#xff0c;这种系统能够有效地整合和管理工程图纸、零部件清单、技术规范、工艺流程等各种数据&#xff0c;为企业提供全面的图纸管理和协作…

typescript:vscode的settings配置文件配置ts语法提示

typescript&#xff1a;vscode的settings配置文件配置ts语法提示 1 找到vscode左下角的齿轮按钮 2 点击Settings&#xff08;或者快捷键ctrl,&#xff09;&#xff1a; 点击右上角的Open Settings(JSON)按钮打开配置文件&#xff1a; 或者ctrlshiftp&#xff0c;搜索settings&…

嵌入式全栈开发学习笔记---Linux基本命令1

目录 cd加路径 相对路径是什么 绝对路径是什么 cd后面没有路径 cd- ls -l ls -a ls -al ls加路径 Linux的命令是数不清的&#xff0c;就像很多应用软件一样&#xff0c;随时都有可能被开发出来。 但是我们目前阶段只需要掌握基本的命令就可以了。 上一篇博文中我已经…

元宇宙APP搭建重点,会用到哪些三方服务?

元宇宙APP的搭建是一个综合性的项目&#xff0c;涉及到众多关键要素和第三方服务。以下是一些元宇宙APP搭建的重点&#xff0c;以及可能用到的第三方服务&#xff1a; 一、搭建重点 技术框架的选择与搭建&#xff1a;元宇宙APP需要稳定、高效的技术框架来支撑其运行。这包括前…

插入排序,搞起来,一路狂奔,数组插入

一点喽 目录 编程实现&#xff1a;程序功能是在一个有序序列中插入一个数后&#xff0c;该数列依然有序 输入测试数据&#xff1a;2 3 5 7 8 23 34 56 78 90 25 程序运行结果&#xff1a;插入之后的数组为 2 3 5 7 8 23 25 34 56 78 90 第一个就…

如何增强交友、婚恋平台、金融等平台的安全性

运营商二要素核验是一种数字身份验证方法&#xff0c;主要使用用户的手机号码和姓名作为核验要素。这两个要素被认为是最基本的用户身份信息&#xff0c;通过运营商的数据库来核实其真实性。 在实际操作中&#xff0c;用户需要提供手机号码和姓名进行验证。应用系统会调用接口…

unity的特性AttriBute详解

unity的特性AttriBute曾经令我大为头疼。因为不动使用的法则&#xff0c;但是教程都是直接就写&#xff0c;卡住就不能继续学下去。令我每一次看到&#xff0c;直接不敢看了。 今天使用文心一言搜索一番&#xff0c;发现&#xff0c;恐惧都是自己想象的&#xff0c;实际上这个…

Docker之存储配置与管理

一、容器本地配置与Docker存储驱动 每个容器都被自动分配了本地存储&#xff0c;也就是内部存储。容器由一个可写容器层和若干只读镜像层组成&#xff0c;容器的数据就存放在这些层中。 容器本地存储采用的是联合文件系统。这种文件系统将其他文件系统合并到一个联合挂载点&a…

Unity类银河恶魔城学习记录15-5,6 p157 Audio time limiter p158 Area sound

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili​​ AreaSound.cs using System.Collections; using System.Collections.G…

Spring boot + Redis + Spring Cache 实现缓存

学习 Redis 的 value 有 5 种常用的数据结构 Redis 存储的是 key-value 结构的数据。key 是字符串类型&#xff0c;value 有 5 种常用的数据结构&#xff1a; Redis 的图形化工具 Another Redis Desktop Manager Spring Data Redis Redis 的 Java 客户端。 Spring Cache Spr…

Pycharm新建工程时使用Python自带解释器的方法

Pycharm新建工程时使用Python自带解释器的方法 新建Project时最好不要新建Python解释器&#xff0c;实践证明&#xff0c;自己新建的Python解释器容易出现各种意想不到的问题。 那么怎样使用Python安装时自带的解释器呢&#xff1f; 看下面的三张截图大家就清楚了。 我的Pyth…

avl excite python二次开发1--python解释器需用内置解释器aws_cmd

avl excite python二次开发1--python解释器需用内置解释器aws_cmd 1、python解释器问题1.1、用外置python解释器&#xff0c;import WSInterface会失败(WSInterface.pyd)1.2、用内置解释器aws_cmd运行py脚本1.3 用内置解释器aws_python执行脚本三级目录 1、python解释器问题 1…

Python_AI库 matplotlib扩展知识

Python_AI库 matplotlib扩展知识 在数据分析和处理的领域里&#xff0c;可视化是一种不可或缺的手段。通过图形化的展示&#xff0c;我们可以更直观地理解数据的分布、趋势和关系。而matplotlib&#xff0c;作为Python中最为流行的数据可视化库之一&#xff0c;以其强大的功能…

Anti Rookit -- 检测隐藏进程

Anti Rookit 一&#xff1a;检测隐藏进程 引言 检测隐藏进程除了众所周知的枚举进程ID之外&#xff0c;还有枚举句柄表的方式。不过今天给大家带来的是第三种方法。 探究 应用层通过接口 C r e a t e P r o c e s s \textcolor{cornflowerblue}{CreateProcess} CreateProcess…

分布式与一致性协议之Paxos算法(二)

Paxos算法 如何达成共识 想象这样一个场景&#xff0c;某地出现突发事件&#xff0c;当地村委会、负责人等在积极研究和搜集解决该事件的解决方案&#xff0c;你也决定参与其中&#xff0c;提交提案&#xff0c;建议一些解决方法。为了和其他村民的提案做区分&#xff0c;你的…

Stability AI 推出稳定音频 2.0:为创作者提供先进的 AI 生成音频 - Circle 阅读助手

概述 Stability AI 的发布再次突破了创新的界限。这一尖端模型以其前身的成功为基础&#xff0c;引入了一系列突破性的功能&#xff0c;有望彻底改变艺术家和音乐家创建和操作音频内容的方式。 Stable Audio 2.0 代表了人工智能生成音频发展的一个重要里程碑&#xff0c;为质量…

【golang学习之旅】Go的 switch 分支语句

系列文章 【golang学习之旅】报错&#xff1a;a declared but not used 【golang学习之旅】Go 的基本数据类型 【golang学习之旅】Go 的循环结构 【golang学习之旅】Go里面 if 条件判断语句 目录 系列文章switch 分支fallthrough 关键字无条件 switch switch 分支 有些时候需…

前端框架编译器之模板编译

编译原理概述 编译原理&#xff1a;是计算机科学的一个分支&#xff0c;研究如何将 高级程序语言 转换为 计算机可执行的目标代码 的技术和理论。 高级程序语言&#xff1a;Python、Java、JavaScript、TypeScript、C、C、Go 等。计算机可执行的目标代码&#xff1a;机器码、汇…

如何使用 Internet Download Manager (IDM) 来加速和优化你的下载体验 IDM 6.41下载神器

在当今信息爆炸的时代&#xff0c;下载文件和媒体内容已成为我们日常生活的一部分。无论是工作学习还是娱乐休闲&#xff0c;我们都需要从互联网上下载各种资源。为了提高下载效率和确保文件完整性&#xff0c;选择一款优秀的下载管理软件至关重要。Internet Download Manager …

四、线段、矩形、圆、椭圆、自定义多边形、边缘轮廓和文本绘制(OpenCvSharp)

功能实现&#xff1a; 对指定图片上进行绘制线段、矩形、圆、椭圆、自定义多边形、边缘轮廓以及自定义文本 一、布局 用到了一个pictureBox和八个button 二、引入命名空间 using System; using System.Collections.Generic; using System.Drawing; using System.Windows.F…