你了解 SpringBoot 在一次 http 请求中耗费了多少内存吗?

SpringBoot一次HTTP请求竟耗费34KB内存?真相大揭秘 通过本文的详细介绍,相信你已经对SpringBoot在处理HTTP请求时的内存消耗有了深入的了解。虽然34KB的内存消耗看起来不多,但在高并发场景下,累积起来的影响不容忽视。希望这篇文章能帮助你在实际工作中更好地优化系统性能,确保系统的稳定性和高效性!如果你有任何问题或建议,欢迎在评论区留言交流。😊🌟。 阅读详情

👉 这是一个或许对你有用的社群

🐱 一对一交流/面试小册/简历优化/求职解惑,欢迎加入「芋道快速开发平台」知识星球。下面是星球提供的部分资料: 

282d122bc24788a5ab8001f1941346e4.gif

👉这是一个或许对你有用的开源项目

国产 Star 破 10w+ 的开源项目,前端包括管理后台 + 微信小程序,后端支持单体和微服务架构。

功能涵盖 RBAC 权限、SaaS 多租户、数据权限、商城、支付、工作流、大屏报表、微信公众号、CRM 等等功能:

  • Boot 仓库:https://gitee.com/zhijiantianya/ruoyi-vue-pro

  • Cloud 仓库:https://gitee.com/zhijiantianya/yudao-cloud

  • 视频教程:https://doc.iocoder.cn

【国内首批】支持 JDK 21 + SpringBoot 3.2.2、JDK 8 + Spring Boot 2.7.18 双版本 

来源:juejin.cn/post/
7416696537684836378

44c8b1018117ef410d6618c75840410e.jpeg


在实际工作中,经常会需要进行在全链路压测,优化 GC参数,优化 JVM 内存分配。

当知道 1 次 RPC 请求和 Http 请求需要的堆内存大小后,你可以精确地计算:指定的并发量之下,系统需申请多少堆内存。同时结合 JVM 新生代堆大小,就能推算出 1 分钟发生多少次 GC,这个 GC频率是否过于频繁?从而针对性的优化。

我们希望 1 次 Rpc、Http 请求申请堆内存足够少,这样可减少 GC 导致的系统停顿,提高系统性能,单机可以支撑更高的并发量。

1次 Http 请求,申请多少堆内存?

1 次 RPC 请求,申请多少堆内存?

如果不亲自实验,无法得出结论。

1. 实验思路

关键动作
  1. 创建SpringBoot新应用(版本2.5.4)。

  2. 新增 Post 接口,供 JMeter 调用。

  3. JMeter(开源压测工具)新建测试计划。每个线程执行2000 次Http接口调用,共10 个线程,总调用 20000 次。

  4. SpringBoot 打印 GC 详细日志,记录GC 前后,新生代申请了多少内存。

Jmeter 调用 20000 次 Http 接口以后,通过手动 GC 的方式触发 GC,通过 GC 详细日志计算压测期间新生代堆内存增长量。(对象基本分配在新生代)

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro

  • 视频教程:https://doc.iocoder.cn/video/

2. SpringBoot 声明 Http 接口

如下代码声明了一个 Post接口 create;创建了 Get 接口,用于触发GC。

@Slf4j
@RestController
public class TestController {

   private AtomicLong count = new AtomicLong(0);

   @ResponseBody
   @RequestMapping(value = "create", method = RequestMethod.POST)
   public String create(@RequestBody Order order) {
      //log.warn("收到提单请求 cnt{}:{}", count.getAndIncrement(), order);
      return "ok";
   }

   @ResponseBody
   @RequestMapping(value = "gc", method = RequestMethod.GET)
   public String gc() {
      System.gc();
      return "ok";
   }
}

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/yudao-cloud

  • 视频教程:https://doc.iocoder.cn/video/

3. JMeter 新建测试计划

3.1 新增线程组

新建线程组,选择 10 个线程,每个线程循环 2000次。

2df8fe50e6e0a0746c20e4166d8ecae5.jpeg a4ad7cea6e86f53b67f3f00bea814b56.jpeg

3.2 新建 Http 默认值

441d65659f15c00a54707fe72176fb0d.jpeg

3.3 新建请求头

由于请求体是 JSON,所以新增请求头 Content-Type

d91a8cfab5b85f91e361df657af26cc0.jpeg

3.4 新建 Http 请求

请求中指定 Url 和 请求体

3d75f8a42c42ad14e8070c0e175a332a.jpeg

4. 实验过程

4.1 启动 SpringBoot应用

堆内存大小 4G,其中新生代内存 2G。SurivivorRadio=8,即每个 Surivivor 占比新生代 1/10。

指定GC日志位置:-Xloggc:/Users/testUser/log/gc.log

java -server 
 -Xmx4g -Xms4g -XX:SurvivorRatio=8 -Xmn2g
 -XX:MetaspaceSize=512m -XX:MaxMetaspaceSize=1g -XX:MaxDirectMemorySize=1g 
 -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCCause -XX:+PrintGCDetails 
 -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintTenuringDistribution 
 -XX:+UnlockDiagnosticVMOptions -XX:ParGCCardsPerStrideChunk=32768 
 -XX:+PrintCommandLineFlags -XX:+UseConcMarkSweepGC -XX:+UseParNewGC 
 -XX:ParallelCMSThreads=6 -XX:+CMSClassUnloadingEnabled 
 -XX:+UseCMSCompactAtFullCollection -XX:+CMSParallelInitialMarkEnabled 
 -XX:+CMSParallelRemarkEnabled -XX:+CMSScavengeBeforeRemark -XX:+PrintHeapAtGC 
 -XX:CMSFullGCsBeforeCompaction=1 -XX:CMSInitiatingOccupancyFraction=70 
 -XX:+UseCMSInitiatingOccupancyOnly -XX:+PrintReferenceGC  
 -XX:+ParallelRefProcEnabled -XX:ReservedCodeCacheSize=256M 
 -Xloggc:/Users/testUser/log/gc.log
 -jar target/activiti-0.0.1-SNAPSHOT.jar

4.2 多次手动 GC

由于JVM 启动过程中,需要加载大量对象,所以我们在压测之前先手动 GC,清理一下存量对象。

curl http://localhost:8080/gc

4.3 Jmeter 启动压测

执行 JMeter压测计划,每次执行会调用 20000 次,

c0c7812cc06d03838eba0117b113e25d.jpeg

4.4 GC 日志解读

GC 以后,新生代 Eden 区已使用内存为 0。GC 前 Eden区大小就是 20000 次 Http 调用所申请的内存总和!

14d935ae5d828b8bb61d0dcfda6adcbd.jpeg

5. 实验结果

SpringBoot 在处理 Http 请求时,即使请求体相对较小,平均每次 Http 调用仍会申请约 34 K 的堆内存 。这一点显得尤为突出,因为请求体仅包含 50 个字符,远远未达到 1K 大小。

然而,每次 Http 请求所消耗的内存却依然高达 34K。这可能是由于在 SpringBoot 的内部处理流程中需要创建多个对象,这些对象的总内存占用显著高于请求体本身。

{"userId": 32898493, "productId":39043, "detail": ""}

在调整 Http 请求后,如将 detail 字段设置为 1200 个字符时,每次 Http 调用平均占用堆内存为 36K。两次实验结果间的差异为 2K,这与 1200 个字符占用的内存大小基本持平(需考虑一定的误差)。

这表明 SpringBoot 内部未进行多次请求体拷贝。

5.1 添加日志打印

log.warn("收到提单请求 cnt{}:{}", count.getAndIncrement(), order);

在打印请求日志后,单次 Http 请求的平均内存使用量达到了 56 KB,比之前增加了整整 20 KB。

然而,当我移除 detail 字段后,单次请求的内存使用骤降至 35.7 KB。

这表明,当日志量较小时,打印日志对内存占用的影响较小。但随着日志大小的增加,内存占用显著上升,这可能触发更频繁地GC,最终导致系统性能明显下降。

因此,建议各位严格控制单条日志的大小,以优化内存使用和系统性能。

4c463eaaab03c5e50455555adce293ed.png

6. 真实的数据

根据以上实验结果可得出结论:单次 HTTP 请求消耗约34KB内存,这并不意味着所有SpringBoot应用的内存消耗都是如此。由于实验所用的代码相对简单,因此34KB可能是内存消耗的最小值。

举例来说,在我司的线上环境中,单次RPC请求的内存消耗在 0.5MB 到 1MB 之间 ,内存占用量相对较大。

这是因为复杂的基础架构、复杂的业务逻辑、复杂的流程、多次下游调用、多次SQL 调用、多次缓存调用、日志打印等等 均需要消耗大量的内存!

在此之前,我一直对新生代 Eden 区高达 5G 的情况下,仍每分钟进行 1-2 次 young GC 感到困惑。

经过粗略计算后发现,如果每次请求消耗 0.5M 内存,当单台服务器每秒并发度达到 500 次时,每分钟需要分配的内存高达 15G。因此,至少需要进行3次 young GC 才能满足需求。


欢迎加入我的知识星球,全面提升技术能力。

👉 加入方式,“长按”或“扫描”下方二维码噢:

f5e23e01a8aa50a5732873f69675f194.png

星球的内容包括:项目实战、面试招聘、源码解析、学习路线。

8827f6335a7ab91e5721fb444f4cd493.png

463ccba9c1e972c709bac3619688ee2a.pngfdea47061c37d7526e23dc648621598b.pnge130283dbc253d305122422d240f775e.png75538ce05f72370322a15dd892d35da4.png

文章有帮助的话,在看,转发吧。
谢谢支持哟 (*^__^*)
AB SCIEX质谱数据分析实战:从PeakView入门到精通 质谱分析是现代生命科学和药物研发中不可或缺的核心技术,它通过测量离子的质荷比来鉴定和定量化合物。其基本原理是将样品离子化后,在电场和磁场中按质荷比分离,最终形成质谱图。这项技术的核心价值在于能够从复杂混合物中高灵敏度、高特异性地获取化合物的定性和定量信息,广泛应用于代谢组学、蛋白质组学、环境监测和药物分析等领域。在实际工作中,高效的数据处理平台至关重要。以AB SCIEX质谱仪生成的.wiff文件为例,其原始数据需要专业软件进行解析。PeakView软件正是这样一个综合平台,它集成了高级数据处理、谱图解析和 阅读详情

相关推荐

电磁流量计模拟前端电路设计与优化

模拟前端电路(AFE)是传感器信号处理的核心环节,通过放大、滤波和模数转换实现信号调理。其设计需重点考虑放大器共模抑制比(CMRR)和ADC分辨率等关键参数,在电磁流量计等工业测量应用中,AD8220仪表放大器与AD7172-2 Σ-Δ型ADC的组合能有效简化传统多级架构。现代过采样技术结合数字滤波可替代模拟滤波器,显著提升系统集成度与测量精度,这种设计方法同样适用于压力传感、生物电信号采集等需要高精度信号调理的场景。

weixin_42602241的博客 618

技术自查第三篇:JVM/GC日志查看篇

调优

banbeisudashui的博客 2928

VisionMaster SDK C#二次开发核心技术指南

以下是基于**VisionMaster SDK C#二次开发核心技术指南**,结合实战案例与关键代码解析,帮助开发者快速掌握工业视觉应用集成。

东城十三 3061

-XX:+PrintHeapAtGC参数使用了解

一般来说,JVM在运行中,是没法直接了解到堆的概况的,只有程序结束后,才会在最后输出堆的概况,参考如下: 可以发现,停止了程序后,才输出了堆的概况。 而如果想要知道每次GC前后,GC堆的概况,就可以加上 【-XX:+PrintHeapAtGC】参数,然后输出结果参考如下: 截图中很直观地输出了GC前后堆的概况。 ...

硅脂味咖啡的博客 4151

新手入门机器学习案例(附源代码)

无

guguo666的博客 6656

从ROS2到ROS1:Lightning-LM激光SLAM模块的移植实践与核心代码解析

本文详细解析了将高性能激光SLAM算法Lightning-LM从ROS2移植到ROS1的完整实践过程。针对ROS1与ROS2在节点初始化、话题通信、参数服务器及TF发布等核心API的差异,文章提供了loc_system和slam模块的核心代码改造示例,并给出了适配catkin的CMakeLists.txt与package.xml配置方案,帮助开发者在现有ROS1生态中高效集成先进的SLAM模块。

weixin_29224529的博客 172

JVM-常用Java虚拟机GC参数

1. 常用Java虚拟机GC基础参数 -XX:+PrintGC 使用该参数启动JVM后,只要遇到GC,就会打印日志。 -XX:+PrintGCDetails 更加详细的GC信息、 -XX:+PrintHeapAtGC 在GC日志输出前后,输出详细的堆信息。 -XX:+PrintGCTimeStamps 在每次GC发生时,额外输出GC发生的时间,该时间为虚拟机启动后的时间偏移量。 -XX:+...

原名又逢乱世。不要放下学习的脚步,毕竟比天天打牌、钓鱼、打游戏更能从内在充实自己。 1207

缺陷检测-金属表面缺陷检测

1介绍 缺陷检测是工业视觉技术中最重要的组成部分。业务广泛,场景丰富,技术难点高、工作量大。针对不同的场景,选择不同的相机和

huneng1991的专栏 5250

从一无所知到无所不知————jvm系列(4)

jvm参数

q3198215426的博客 708

双馈风机并网系统宽频振荡机理与抑制方法研究

双馈风机并网系统宽频振荡分析与抑制 摘要:本文研究了双馈风机(DFIG)接入弱电网引发的宽频振荡问题。通过建立DFIG并网系统阻抗模型,分析了锁相环带宽、电流环带宽等参数对阻抗特性的影响。研究揭示了DFIG与电网阻抗交互导致交截频率处相位差超过180°的振荡机理。提出基于锁相环优化的阻抗重塑抑制策略,采用电压补偿和陷波器改善系统稳定性。仿真结果表明,该方法能有效降低相位差约10°-168°,显著抑制宽频振荡。代码实现了阻抗建模、稳定性分析和抑制策略验证,为工程应用提供了理论依据。

huanghm88的专栏 320

沁恒CH32V30X学习笔记02--GPIO的使用教程及2次封装驱动

刚复位后,GPIO 口运行在初始状态,这时大多数 IO 口都是运行在状态所有的 GPIO 口都可以被配置外部中断输入通道,但一个外部中断输入通道最多只能映射到一个GPIO 引脚上,且外部中断通道的序号必须和 GPIO 端口的位号一致,,两方都是一对一的关系。复用功能。

Car12 706

SpringBoot 在一次 http 请求中耗费了多少内存?

其实问“一次请求耗多少内存”,没有固定答案,我认为核心不是纠结具体的数字,而是要有“内存意识”——知道哪些代码会耗内存,高并发下该怎么优化。普通的业务接口,单次消耗几十 KB 其实很正常,只要不是几百 KB 甚至几 MB,一般都没问题。但如果是每秒几千、几万的高并发接口,哪怕单次只耗 10 KB,一秒钟也会耗掉几十 MB 内存,这时候就得精打细算了。总的来说,SpringBoot 本身的基础开销是固定的,我们能优化的主要是业务代码里的对象创建和数据传输量。

记录学习路上的每一个 “啊哈!” 时刻 欢迎交流,共同进步! 1220

已解决“TimeouEror [WinEror 10060由于连接方在一段时间后没有正确答复 或连接的主机没有反应,连接尝试失败“,亲测有效!!!

已解决"TimeouEror [WinEror 10060由于连接方在一段时间后没有正确答复 或连接的主机没有反应,连接尝试失败",亲测有效!!!

wbajsjhhhhh的博客 1万+

SpringBoot 在一次 http 请求中耗费了多少内存

在实际工作中,经常会需要进行在全链路压测,优化 GC参数,优化 JVM 内存分配。当知道 1 次 RPC 请求和 Http 请求需要的堆内存大小后,你可以精确地计算:指定的并发量之下,系统需申请多少堆内存。同时结合 JVM 新生代堆大小,就能推算出 1 分钟发生多少次 GC,这个 GC频率是否过于频繁?从而针对性的优化。我们希望 1 次 Rpc、Http 请求申请堆内存足够少,这样可减少 GC 导致的系统停顿,提高系统性能,单机可以支撑更高的并发量。1次 Http 请求,申请多少堆内存?

tangjieqing的博客 735

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

上一篇: SkyWalking VS ELK 实现日志追踪,哪个更牛?
下一篇: 是时候优化了:告别繁琐操作,实现一次登录产品互通!
公众号-芋道源码
博客等级 码龄10年 1634粉丝 377原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值