性能测试的目标不是把系统压垮,而是找到在满足预期性能指标的前提下,系统能承载的最大负载以及定位限制这一负载的瓶颈点。
一、Web 应用性能短板分析思路
1. 性能标准
响应时间:端到端耗时,重点重视平均值和 90/95/99 分位值。
吞吐量:单位时间内完成的请求数(TPS/QPS)。
并发用户数:同时操作或在线用户数,需要区分“绝对并发”和“业务并发”。
错误率:压力下开始出现 5xx、连接超时等错误的临界点。
资源利用率:CPU、内存、磁盘 I/O、网络带宽、连接数等。
2. 分层排查
从用户侧到后端,逐层缩小嫌疑范围:
客户端/网络层:带宽短板、DNS 延迟、CDN 回源、防火墙限制。
Web 容器/反向代理:Nginx/Apache 连接数、keepalive 配置、静态资源处理。
应用层:编程语言/框架线程池(如 Tomcat 线程池)、代码锁竞争、GC 停顿、缓存方法。
中间件层:消息队列积压、Redis 热 key、RPC 超时等。
数据库层:慢查询、锁等待/死锁、连接池耗尽、索引缺失、大事务。
操作系统/硬件层:CPU 软中断、内存换页、磁盘 IOPS 不足。
3. 常见短板及Linux 环境排查命令
CPU 短板:top 看 us(用户态)、sy(内核态)、wa(IO等待)。wa 高一般指向磁盘 I/O;us 高且用户线程多可能是代码或 GC。
内存短板:free -h,如果 swap 使用突增,一般内存不足触发 GC 或 OOM。
磁盘 I/O:iostat -x 1,观察 %util 和 await。数据库服务器需特别重视。
网络短板:sar -n DEV 1 或 nload,检查带宽是不是打满。重视 TIME_WAIT 连接数:ss -s。
应用层短板:JVM 监控(jstat -gcutil 看 FGC 频率和耗時)、线程 dump(jstack 看线程卡在什么地方,如 waiting for connection pool)。
数据库:开启慢查询日志,分析 pt-query-digest;查看锁 SHOW ENGINE INNODB STATUS;连接数 SHOW PROCESSLIST。
二、JMeter性能测试实践
1. 测试设计
确定测试目的:新系统预估容量、旧系统考虑升级、寻找并发拐点等。
需求转化:如系统需支持5000在线用户,某接口响应时间小于2秒转化为对该接口施压,观察500并发不断10分钟时的TPS和响应时间。
业务建模:选取接口(登录、下单、查询),按线上比例混合。如10% 登录+50% 浏览+40%下单。
2. JMeter脚本结构
测试计划:运行线程组前可添加setUp Thread Group(造数据)和tearDown(清理)。
线程组:设置线程数(虚拟用户数)、Ramp-Up时间、循环次数或不断时间。
负载测试可勾选 Scheduler 设置不断时长,让压力平滑。
配置元件:
HTTP Request Defaults:统一协议、服务器 IP、端口。
HTTP Cookie Manager:自动处理 Session 维持登录。
HTTP Header Manager:添加 Content-Type、Token 等。
CSV Data Set Config:参数化用户名、密码,避免缓存命中等导致的失真。
取样器:HTTP Request 填写途径和方法,参数、消息体。
思路控制器:Transaction Controller 将多个请求包裹为一个事务,用于测量业务整体耗时。Throughput Controller分配业务比例。
定时器:Uniform Random Timer 或 Gaussian Random Timer 模拟思考时间,更贴近真实。
断言:Response Assertion 检查响应码或内容,断言失败会标记样本错误。
监听器:运行中可临时使用View Results Tree调试;正式执行只用简单报告(Aggregate Report),避免GUI消耗。
3. 非GUI方式场景执行
bash
# 执行并生成 jtl 结果文件
jmeter -n -t test_plan.jmx -l result.jtl -e -o report/
必须用非 GUI 方式,否则客户端本身成为短板。
当单机 JMeter 产生压力不足时,使用分布式:
master 控制多台 slave,各自运行 jmeter-server,结果回传合并。
4. 结果拐点分析
拿到Aggregate Report后:
#Samples、Average、Median、90% Line、95% Line、99% Line、Min/Max、Error%、Throughput。
变化规律:逐渐增加线程组并发用户数(如 50、100、200、300...),记录对应的 TPS 和响应时间。
理想线性区:TPS 随并发数线性增长,响应时间基本平稳或轻微增加。
拐点:再增加并发,TPS 增长明显放缓甚至下降,响应时间急剧上升,错误率上升。此时服务端某项资源达到极限,即为性能短板点。
结合服务端监控:发现拐点时,观察此时哪项资源(CPU、内存、I/O、数据库连接数)已满或接近极限,从而定位短板。
三、常见问题定位优化
将常见现象和对应分析整理如下,方便快速对照。
场景一:并发很低就报错,TPS上不去
可能原因:连接池不足(数据库连接池或 HTTP 连接池)。
排查方法:查看应用连接池等待线程数,数据库执行 SHOW PROCESSLIST 看连接数。
优化方向:适当增大连接池、优化慢 SQL 缩短连接占用时间。
场景二:响应时间随并发线性增长,TPS持平不增
可能原因:线程等待锁(代码同步块或数据库行锁)。
排查方法:线程 dump 发现大量 BLOCKED 状态线程;数据库查看 innodb_lock_waits。
优化方向:减小锁粒度,将同步思路改为异步,优化 SQL(建立索引、减小事务范围)。
场景三:TPS在高负载下突然掉零,一段时间后自动恢复
可能原因:JVM 发生 Full GC 停顿。
排查方法:jstat -gc 观察 Full GC 频率和每次耗时。
优化方向:调优 JVM 内存参数(如增大新生代、减少对象创建),排查内存泄漏。
场景四:大量请求返回 502/504 错误
可能原因:后端应用线程池满或处理超时。
排查方法:查看 Nginx 错误日志,获取应用线程 dump(所有线程均处于繁忙或等待状态)。
优化方向:增加 Tomcat 等工作线程数,优化下游调用超时时间,加入熔断降级机制。
场景五:CPU 使用率不高,但响应慢、错误率高
可能原因:网络连接队列满(SYN backlog 不足)或带宽打满。
排查方法:netstat -s 查看 listen queue overflow,ss -lnt 看 Recv-Q 积压。
优化方向:调整内核参数 net.core.somaxconn,扩容带宽或开启压缩传输。
场景六:数据库压力大,但单条 SQL 执行很快
可能原因:大量重复的简单查询未命中缓存。
排查方法:监控缓存命中率,检查 Redis 慢查询日志。
优化方向:引入本地缓存或分布式缓存,做好热点数据预热。
性能短板分析是一个假设-证实的循环:借助 JMeter 制造可测量压力,用系统监控标准锁定资源方面短板,再深入到应用和代码层寻找根因。测试脚本的真实性(参数化、思考时间、缓存处理)直接决定结果是不是可信,脚本设计需要投入足够精力。将 JMeter 的聚合数据和 OS、中间件的监控叠加对比,才能在出现拐点时快速判断是CPU先满,还是数据库连接池先耗尽,最后给出有数据支撑的扩容或优化方案。