CPU性能优化干货总结
一、背景
部门成立专项组,对数智平台和站务系统做性能优化,其中目标之一为降低服务端硬件成本,即在32G内存、CPU银牌的配置下,能支撑1万+发客量。要达到此目标,需通过压力测试并配合监控系统,以QPS、RPS、接口响应时间、接口成功率、SQL耗时、JVM运行情况、CPU和内存运行情况等数据指标为依据,找出系统中存在的性能瓶颈。
二、压测准备工作
1、测试服务器
1.1、准备一台测试服务器,配置如下:
| 硬件类型 | 硬件配置 | 备注 |
|---|---|---|
| CPU | i5-9400 CPU @ 2.90GHz @ 6 Core 6 Thread | 普通办公电脑 |
| 内存 | DIMM DDR4 @ 16G 2400Mhz + 8G 2400Mhz | --- |
| 硬盘 | KINGSTON SA400M8 SSD 240G | 性能优于机械硬盘50% |
| 网卡 | RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller | --- |
1.2、准备千兆交换机
因压力机的网卡为100M,当请求超过100user后数据量超过压力机带宽限制,压测数据突发提升,因此更换千兆交换机。
2、CAT监控
为了在压测过程中,实时监控业务系统运行情况,采用了目前中心系统已成熟使用的cat监控,其原理是通过埋点数据上送,并生成各类可视化报表,可监控的指标包括JVM、接口、SQL、异常告警等。
cat官方地址:https://github.com/dianping/cat
三、压测关键过程
1、第一次压测情况
| 用户数 | QPS | 压测情况说明 | 出票量 |
|---|---|---|---|
| 10 | 33 | CPU80%,tomcat-zw占用15%;影响正常业务 | 10分钟/3540张 |
| 20 | 27 | CPU80%,tomcat-zw占用15%;影响正常业务 | 10分钟/4440张 |
CPU负载情况:

通过以上数据可以看出,在10个并发请求情况下,CPU基本打满,业务系统已无法正常运行。提升到20个并发请求后,QPS不增返降,说明系统已无法支撑更多请求。
2、数智平台性能排查及解决过程
2.1、接口缓存
- 以上数据显示,站务系统tomcat-zw仅占用了15%的CPU,需要找到其他65%消耗在哪。
- 通过top命令发现station-base占用CPU超过tomcat-zw,按照业务复杂度划分来看,及其不合理,于是需要找出station-base占用高的原因。
- 首先,找到station-base的进程ID:ps -ef | grep station-base
- 再查看进程ID找到占用高的线程ID:top -Hp 1061
- 再根据线程ID找到具体堆栈信息
线程ID转化为16进制(TID):printf "%x\n" TID;
JVM堆栈中查找线程信息:jstack PID | grep TID -A100;- 发现较多线程在执行以下两个接口,但未做缓存:
/base/openApi/line/getAllLineDownSiteBySiteNos
/base/openApi/line/getStationLineByLineNo
2.2、网关优化
2.2.1、spring gateway向/tmp文件夹创建大量临时文件夹,导致/tmp目录卡死
- 使用jstack命令查看吃cpu的线程运行情况如下图:
- 登录服务器查看/tmp目录大小,发现存在大量临时文件,乃至ls /tmp 命令卡死
- 执行rm -rf /tmp情况文件夹,因文件夹太多无法删除,因此更换删除命令find . -name "*" -print | xargs rm -rf,10秒清空文件夹。
- 查看相关资料及源码后,确认数智平台当前使用的Hoxton.SR12(依赖的spring-web 5.2.15版本)版本存在此类问题:
-官网证实链接1:https://github.com/spring-projects/spring-framework/issues/27094
-官网证实链接2:https://github.com/spring-projects/spring-framework/issues/27092
- 解决措施:将spring-web 5.2.15升级到5.2.16
2.2.2、自定义过滤器代码本身问题排除
- 因gateway需要对请求和响应进行参数重新包装,故需要自定义过滤器,分别是请求过滤器(ModifyRequestGatewayFilterFactory)和响应过滤器(ModifyResponseGatewayFilterFactory)进行拦截处理,为避免网关响应时间受自定义过滤器的影响,直接将过滤器取消,对spring cloud gateway原生代码进行请求压测,经实测后,性能并为明显提升,可以排除自定义过滤器的问题。
2.2.3、Reactor(netty)工作线程组及epoll请求处理线程配置


但从接口的平均响应时间来看,依然在500ms左右。于是通过资料查找,怀疑为netty问题,netty源码的配置为:
DEFAULT_IO_WORKER_COUNT:如果环境变量有设置reactor.ipc.netty.workerCount,则用该值;没有设置则取Math.max(Runtime.getRuntime().availableProcessors(), 4)))
DEFAULT_IO_SELECT_COUNT:如果环境变量有设置reactor.ipc.netty.selectCount,则用该值;没有设置则取-1,表示没有selector thread
默认配置下,通过artha可以看出Reactor-http-epoll处理线程如下图:
可以看出,netty框架默认情况下,按测试服务器配置,工作线程为6且未使用selector线程组。于是增加以下环境变量:
@Bean
public ReactorResourceFactory reactorClientResourceFactory() {
// 配置线程组
System.setProperty("reactor.netty.ioSelectCount","1");
// 这里工作线程数为2-4倍都可以。看具体情况
int ioWorkerCount = Math.max(Runtime.getRuntime().availableProcessors()*3, 4));
System.setProperty("reactor.netty.ioWorkerCount",String.valueOf(ioWorkerCount);
return new ReactorResourceFactory();
}
再次通过arthas可以看出Reactor-http-epoll处理线程如下图:
配置完成后,再次压测,RPS达到3300,平均响应时间降低到150ms以内
2.2.4、logback同步写日志改为异步
通过cpu火焰图发现在处理大量请求时,自定义的sql打印插件频繁的输出sql语句,而且logback在默认情况下采用同步写日志,而同步阻塞写,会拖慢业务方法执行速度,下图是将logback改成异步的配置
2.2.5、网关优化总结
- 1、自定义过滤器本身问题排除
- 2、使用centos系统提供的一些硬件资源命令来分析高消耗cpu或者io线程,使用查此线程在jvm中的运行详情以此来寻找问题解决方向
- 3、分析jvm中的线程来判断定位可能出问题的代码(比如2.2.1)
- 4、通过关键信息寻找问题原因或解决方案(最好是来自官网或者github官方仓库的issues)
- 5、透过现象看本质,通过各种辅助工具或命令来排查cpu和io高占用的线程,以此数据作为解决问题的基础支撑
3、站务系统性能排查及解决过程
3.1 全局filter校验token未做缓存

通过链路监控发现,zw-station-ticket模块在接收到购票请求到第一次执行SQL查询之间,有大约600ms损耗。通过查看代码发现,可能是因为全局token校验接口未做缓存导致。优化完成后查看监控数据,token校验耗时正常。
3.2 Transaction注解问题

再次压测,观测调用链路,仍然发现在进入购票接口后,有时间损耗,通过排查代码发现,在购票和锁票方法上面有@Transaction注解,时间损耗的可能原因是:
当 Spring 遇到该注解时,会自动从数据库连接池中获取 connection,并开启事务然后绑定到 ThreadLocal 上,对于@Transactional注解包裹的整个方法都是使用同一个connection连接 。如果我们出现了耗时的操作,比如第三方接口调用,业务逻辑复杂,大批量数据处理等就会导致我们我们占用这个connection的时间会很长,数据库连接一直被占用不释放。
因此去掉事务注解后,再次观测数据,空白时间损耗问题解决。

后续解决思路:对事务方法进行拆分,尽量让事务变小,变快,减小事务的颗粒度。否则,可能出现:
- 数据库连接池被占满,应用无法获取连接资源;
- 容易引发数据库死锁;
- 数据库回滚时间长;
- 在主从架构中会导致主从延时变大。
3.3 logback日志问题
通过以上方式优化完成后,发现tomcat-zw模块依然占用比较大的CPU,在150%-300%之间。于是,准备通过async-profiler工具,查看耗CPU的详细堆栈信息。
- 第一步,下载async-profiler-2.8.3-linux-x64.tar.gz,并解压
- 第二步,执行数据采集命令,生成CPU运行火焰图:./profiler.sh -d 60 -f ./nacos.html PID

通过火焰图发现,基本所有CPU都在执行logback日志打印。
于是,对logback配置文件进行优化:
- 去掉控制台打印
- 改为异步合并写日志

优化完成后再次压测,RPS由原23.7提高到222;平均响应时间由原1447ms降低为1082ms;
优化前:

优化后:

4、其他优化
- 为减少CPU消耗,JVM垃圾收集器由CMS改为G1
CPU性能优化干货总结的更多相关文章
- [Unity优化] Unity CPU性能优化
前段时间本人转战unity手游,由于作者(Chwen)之前参与端游开发,有些端游的经验可以直接移植到手游,比如项目框架架构.代码设计.部分性能分析,而对于移动终端而言,CPU.内存.显卡甚至电池等硬件 ...
- Linux性能优化从入门到实战:07 CPU篇:CPU性能优化方法
性能优化方法论 动手优化性能之前,需要明确以下三个问题: (1)如何评估性能优化的效果? 确定性能的量化指标.测试优化前的性能指标.测试优化后的性能指标. 量化指标的选择.至少要从应用程序 ...
- 【转载】PHP性能优化干货
PHP优化对于PHP的优化主要是对php.ini中的相关主要参数进行合理调整和设置,以下我们就来看看php.ini中的一些对性能影响较大的参数应该如何设置. # vi /etc/php.ini (1) ...
- CPU性能优化
原创转载请注明出处:https://www.cnblogs.com/agilestyle/p/11521331.html CPU性能指标 根据指标找工具 根据工具查指标 top.vmstat 和 pi ...
- 《Linux 性能优化实战—倪朋飞 》学习笔记 CPU 篇
平均负载 指单位时间内,系统处于可运行状态和不可中断状态的平均进程数,即平均活跃进程数 可运行状态:正在使用CPU或者正在等待CPU 的进程,也就是我们常用 ps 命令看到的,处于 R 状态 (Run ...
- Linux性能优化实战CPU篇之总结(四)
一.分析CPU瓶颈 1,性能指标 a>CPU使用率 CPU使用率描述了非空闲时间占总CPU时间的百分比,根据CPU上运行任务的不同可以分为:用户CPU.系统CPU.等待I/O CPU.软中断和硬 ...
- KVM性能优化学习笔记
本学习笔记系列都是采用CentOS6.x操作系统,KVM虚拟机的管理也是采用virsh方式,网上的很多的文章都基于ubuntu高版本内核下,KVM的一些新的特性支持更好,本文只是记录了CentOS6. ...
- 揭秘重度MMORPG手游后台性能优化方案
本文节选自<2018腾讯移动游戏技术评审标准与实践案例>手册,由腾讯互娱工程师王杰分享<仙剑奇侠传online>项目中游戏后台的优化经验,深度解析寻路算法.视野管理.内存优化. ...
- Linux性能优化实战学习笔记:第五十六讲
一.上节回顾 上一节,我带你一起梳理了,性能问题分析的一般步骤.先带你简单回顾一下. 我们可以从系统资源瓶颈和应用程序瓶颈,这两个角度来分析性能问题的根源. 从系统资源瓶颈的角度来说,USE 法是最为 ...
随机推荐
- cloudwu/coroutine 源码分析
1 与其它协程库使用对比 这个 C 协程库是云风(cloudwu) 写的,其接口风格与 Lua 协程类似,并且都是非对称 stackful 协程.这个是源代码中的示例: #include " ...
- 『忘了再学』Shell基础 — 27、AWK编程的介绍和基本使用
目录 1.AWK介绍 (1)AWK概述 (2)printf格式化输出 (3)printf命令说明 2.AWK的基本使用 (1)AWK命令说明 (2)AWK命令使用 1.AWK介绍 (1)AWK概述 A ...
- redis主从复制(九)
先来简单了解下redis中提供的集群策略, 虽然redis有持久化功能能够保障redis服务器宕机也能恢复并且只有少量的数据损失,但是由于所有数据在一台服务器上,如果这台服务器出现硬盘故障,那就算是有 ...
- 记一次APP渗透登录验证绕过思路
前言: 起初是抓包时候查看返回状态码不一致,所以觉得是否可以通过修改状态码来达到绕过的目的,但是拦截响应包再替换手速不够,技术大哥就去搜了下,找到了一个方法,可以自动替换响应包内容. 在偏下方一点的地 ...
- SAP FPM 相关包 APB_FPM_CORE
related interface: APB_FPM_COREAPB_FPM_CORE_4_EXT_SCAPB_FPM_CORE_INTERNALAPB_FPM_CORE_RESTRICTED
- Linux安装MySQL,数据库工具连接Linux的MySQL
1.centOS中默认安装了MariaDB,需要先进行卸载 rpm -qa | grep -i mariadb rpm -e --nodeps 上面查出来的mariadb 2.下载MySQL仓库并安装 ...
- hadoop MapReduce运营商案例关于用户基站停留数据统计
注 如果需要文件和代码的话可评论区留言邮箱,我给你发源代码 本文来自博客园,作者:Arway,转载请注明原文链接:https://www.cnblogs.com/cenjw/p/hadoop-mapR ...
- 全新升级的AOP框架Dora.Interception[汇总,共6篇]
多年之前利用IL Emit写了一个名为Dora.Interception(github地址,觉得不错不妨给一颗星)的AOP框架.前几天利用Roslyn的Source Generator对自己为公司写的 ...
- [BJDCTF2020]The mystery of ip|[CISCN2019 华东南赛区]Web11|SSTI注入
记录一下BUUCTF中两个类似的SSTI注入关卡 [BJDCTF2020]The mystery of ip-1: 1.打开之后显示如下: 2.在hint.php中进行了相关提示,如下: 3.既然获取 ...
- 不要让Microsoft edge 打开IE浏览器的设置(兼容性问题)
1打开Microsoft edge 2 打开设置 3 搜索栏搜索IE,打开即可







