记一次压测QPS上不去的排查经历

背景

由于架构变更,服务与服务之间职责发生变更,故而进行项目重构,而个人中心,是一个重要的入口,该接口开发后,需要进行压测,并结合线上的访问量,进而评估所需要的资源

问题

压测过程中,随着并发数的增加,CPU占用越来越高,但是TPS却依旧没有什么变化,对比之前老系统的压测结果,明显就有异常

因为下游系统并不是直接调用真实系统,而是mock,之前也有这种情况,mock占用资源导致TPS上不去的情况,所以让测试将下游系统也部署上去,真实调用下游看看压测结果,发现还是一样,没有改变

排查

1.通过日志排查

因为能直接接触到的,就是日志了,通过日志分析接口,发现大部分接口耗时都好几秒,然后看调用下游,调用redis前后的日志,发现调用的耗时其实算是正常的;去看其他日志的打印间隔,发现有两行日志之间的时间间隔比较大,定位到代码具体位置,发现这两行日志之间其实都没啥逻辑,对比该接口其他日志结果,发现耗时的地方并不相同,猜想是full gc导致的停顿

2.通过gc日志验证猜想

找到gc日志,查询到所有full gc的日志,发现确实full gc挺频繁的,但是光看gc日志,并不能得出什么信息

3.通过工具定位原因

使用jdk自带的监测工具jvisualvm.exe(jdk/bin目录中)

连接到远程应用,需要应用启动的时候增加JVM参数,暴露出端口,才可以通过下图红框来连接,这里通过本地连接做个样例

连接后,整个界面大概就是这样,首页的看板,可以实时反应出CPU,堆情况等信息

当时CPU的情况大概如下图红线(所有图标,都大概画了当时的情形,以红线为准

压测的整个过程,CPU直接满载了,并且居高不下,一直到压测结束,才降下来

看堆的情况,发现gc频繁,但是gc的曲线如下图红线,每次触发gc后,都只回收一部分,另一部分回收不掉,堆内存持续增长。这样应用运行久了,肯定会内存溢出的。

初步猜测,应该是一直产生大对象,并且被长时间持有,释放不了

通过抽样器,大概反应出堆的情况,发现并没有持有大对象,没有异常的情况,就很奇怪,为什么一直堆一直回收不了,一直持续增长?

下图只是说明在哪里看,给个示例

观察一下CPU的情况,发现有几个方法,一直占用了大量的CPU资源,而且都是日志打印的方法,这就很不对劲了

代码定位到具体的类,发现是做日志脱敏的日志扩展类

下图只是说明在哪里看,给个示例

所以到这里可以初步认定是日志脱敏消耗了大量的CPU资源导致的

4.验证结论

尝试着关掉日志脱敏,重新进行压测,发现压测结果正常,随着并发数的增加,TPS也增加了,CPU正常上升,不存在大量接口延时的情况

观察堆的情况,发现垃圾回收没有那么频繁了,并且触发垃圾回收后,也能回收掉所有垃圾,如下图红线,很平稳,不像之前堆内存一直在持续增长,所以这里验证了前一步的猜想,是日志脱敏导致的

5.解决方案

由于监管要求,日志脱敏并不能关闭,所以得另外找解决办法,既然是日志脱敏消耗大量的CPU资源,那只能对日志进行处理了

分析发现,因为内部框架对于请求/响应报文重复打印了好几次,并且有两个接口,是存在大报文的(由于工作量原因,某些配置表当期没安排迁移,只能通过老系统提供接口,获取整个配置表)

尝试着把这两个接口的配置都清空,开启日志脱敏的情况下,再进行压测,发现堆内存变化也是正常的

因为配置表暂时没人力可以做迁移,最后只能推动框架的负责人,优化日志,减少日志重复打印,避免日志脱敏占用大量CPU资源,但是隐患依旧是存在的,后续推动配置表的迁移

原因

日志脱敏,因为需要做正则匹配,但是大量的日志,以及都是大报文,会消耗特别多的CPU资源

系统是对C的,为了减少延迟,使用的是CMS垃圾回收器

CMS垃圾回收器,触发一次full gc,只会在初期暂停所有应用线程,标记没有被引用的对象,后面并发标记和并发回收,并不会暂停应用,这样是为了减少应用的延迟时间,但由于CPU资源被日志脱敏大量消耗了,导致垃圾回收线程抢占不到CPU资源,回收缓慢,旧垃圾没回收完,新垃圾又产生,堆内存就呈现出持续增长的情况

<think>嗯,用户这次的问题是关于集群性能试中指标判断的专业问题。从对话历史看,用户之前已经理解了集群监控需要覆盖所有节点,现在进一步深入到性能试的指标分析层面,说明用户正在搭建或优化一个分布式系统。 用户引用了五段技术资料,其中[1][2][4][5]都是关于性能试的指标定义和案例分析,特别是[5]提到“拐点”概念,这与用户问题直接相关。用户的核心疑问是:当集群中个别节点CPU飙高但整体平均不高时,是否算性能达标。 这个问题其实触及了分布式系统性能评估的关键矛盾——全局视角与局部瓶颈的权衡。用户可能正在经历这样的困扰:报告显示集群整体CPU平均只有50%,但某个节点持续在80%以上,运维团队认为资源充足,而开发团队却收到该节点上服务的超时报警。 需要从三个维度帮用户理清: 首先是技术原理层面,必须解释为什么单节点高负载会影响全局。比如当某个节点成为瓶颈时,即使其他节点空闲,整个系统的吞吐量也会受限于该节点(类似木桶效应)。可以引用[5]的QPS拐点概念说明。 其次是工程实践层面,要给出具体的判断标准。用户提供的资料[2]提到CPU利用率应低于70%,这个阈值可以作为参考。但需要补充说明:对于有状态服务(如数据库分片)和无状态服务(如Web应用),单节点负载的容忍度是不同的。 最后是解决方案层面,应该提供可操作的排查路径。比如教用户如何用PromQL定位具体超标的节点(引用对话历史里的监控方案),以及如何区分暂时性峰值和持续性高负载(引用[4]的分位数统计方法)。 用户引用的案例[1]中电商公司优化智能客服的例子很有参考价值——他们不仅关注整体延迟,还通过增加边缘节点解决了局部热点问题。这提示我们需要强调:在分布式系统中,任何单点瓶颈都可能导致SLA不达标,即使整体资源充足。 关于指标计算,需要提醒用户注意P95/P99等分位值(引用[4])。例如某个节点CPU偶尔冲到85%可能可以接受,但若其P95值持续高于80%就必须处理。最好用LaTeX公式展示下分位值计算方法,比如:$$ P_{95} = \inf\left\{ x \mid F(x) \geq 0.95 \right\} $$ 最后生成的延伸问题要引导用户深入:从单节点问题引申到自动扩缩容策略(应对热点)、资源调度优化(避免负载不均)等进阶话题。特别是用户提到“集群模式”,可能暗示着Kubernetes环境,后续可以探讨HPA配置技巧。</think>在集群性能试中,**仅关注整体平均 CPU 使用率不足够**,即使集群平均 CPU 不高,但存在单节点 CPU 持续超过 80% 的情况,**系统性能仍可能不达标**。原因和判断依据如下: --- ### 一、为何单节点高负载是风险点? 1. **木桶效应** 集群性能受最弱节点制约,单节点 CPU 持续 >80% 可能导致: - 该节点处理延迟飙升(如 P95 延迟超阈值) - 引发连锁故障(如该节点宕机导致负载转移至其他节点) 2. **资源分配不均的隐患** 整体平均 CPU 低可能掩盖问题: ```bash # 示例:4节点集群负载情况 节点1: 85% 节点2: 30% 节点3: 25% 节点4: 20% => 平均 CPU = (85+30+25+20)/4 = 40% (看似健康) ``` 但节点1已达风险水位(引用[2]建议 CPU <70% 的余量原则)。 3. **SLA 违约风险** 如引用[1]案例要求“99%请求延迟<200ms”,若高负载节点处理请求超时,将直接违反 SLA。 --- ### 二、判断是否达标的三个关键维度 | **维度** | **达标标准** | **本例是否达标?** | |------------------|-----------------------------------------------------------------------------|--------------------------| | **整体吞吐量** | QPS/RPS 满足预期且无错误率上升(引用[2]要求错误率<0.01%) | ✓ 可能达标 | | **全局延迟** | 平均/P95延迟符合要求(如引用[2]: 平均<100ms, P95<150ms) | 需验证延迟数据 | | **单节点健康度** | 所有节点 CPU <70% (引用[2]),且无持续 >80% 的节点 | ✗ **不达标** | > 📌 **结论**:**单节点 CPU >80% 属于性能缺陷**,需优化(即使其他指标正常)。 --- ### 三、问题定位与优化方案 #### 1. 定位瓶颈节点 通过 Prometheus 快速定位高负载节点: ```promql # 查询 CPU >80% 的节点 (持续5分钟) 100 - (avg by(instance)(irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80 ``` #### 2. 根因分析方向 | **可能原因** | **验证方法** | |----------------------------|-----------------------------------------------------------------------------| | **负载均衡失效** | 检查流量分发策略(如 Nginx upstream 配置) | | **资源调度不均** | 分析容器编排工具(如 K8s)的 Request/Limit 设置 | | **单节点有状态服务瓶颈** | 检查该节点是否运行数据库等有状态服务(引用[1]边缘节点优化案例) | | **热点数据/请求倾斜** | 分析该节点处理的请求特征(如特定用户或商品查询) | #### 3. 优化措施(引用案例实践) - **动态扩缩容**:对高负载节点自动扩容(如 K8s HPA) - **负载均衡优化**:调整权重或采用一致性哈希(避免请求倾斜) - **计算卸载**:如引用[1]将计算密集型任务移至边缘节点 - **资源预留**:按引用[5]原则预留缓冲(日常负载 ≤ 拐点 QPS 的 70%) --- ### 四、性能试建议 1. **监控覆盖所有节点** 时需采集**每个节点**的 CPU/内存/网络指标(引用对话历史监控方案)。 2. **关注分位数延迟** 尤其检查高负载节点的 P95/P99 延迟(引用[4]),确保符合 $$ P99 < \text{SLA阈值} $$。 3. **模拟真实场景** 按引用[3]方法设计力模型,需包含: - 突发流量峰值(如引用[2]双11场景) - 长时间稳态力(验证资源泄露) > ✅ **达标核心原则**:**所有节点**关键指标(CPU/延迟/错误率)同时满足要求,且通过引用[5]的**拐点验证**预留足够缓冲。 --- ### 相关问题 1. 如何设计集群性能试的节点监控覆盖策略? 2. Kubernetes 中如何自动扩展高负载节点的副本? 3. 负载均衡配置不当导致请求倾斜的排查方法? 4. 性能试中如何根据拐点(QPS)确定最佳容器副本数? 5. PromQL 如何统计集群中异常节点(CPU>80%)的比例? [^1]: 单节点高负载导致延迟超标需优化部署 [^2]: CPU 利用率阈值设定原则 [^3]: 性能试中节点级指标采集方法 [^4]: 延迟分位数对用户体验的影响 [^5]: 系统容量规划与拐点缓冲设计
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值