使用wrk进行服务器压测
在日常开发中,我们常以为“接口能用就行”,但真正高并发场景下,一个慢 SQL 就能让整个系统瘫痪。
最近在对项目管理系统进行性能压测时,发现某个 POST 接口 QPS 不足 200,延迟高达 1.7 秒,而另一个 GET 接口却能跑到 1w+ QPS,记录一下从压测 → 定位 → 优化 → 验证,完整还原一次真实的性能调优过程。
1、apipost的性能测试


使用apipost做性能测试 设置100VU(虚拟用户)发现测试效果很不理想,猜测原因是apipost的测试性能测试为串行测试,并非真实100并发场景下的测试,所以测试结果无参考价值
2、wrk测试
经过一番查找,锁定了一个叫 wrk的压测工具,轻量、高效、支持 Lua 脚本,适合模拟真实的高并发 POST 请求
# 安装依赖
sudo yum groupinstall -y "Development Tools"
sudo yum install -y git
# 克隆并编译 wrk
git clone https://github.com/wg/wrk.git
cd wrk
make
sudo cp wrk /usr/local/bin
#验证安装
wrk --version
#输出
wrk 4.1.0 [epoll] Copyright (C) 2012 Gautam Tandon
运行压测
wrk -t12 -c100 -d30s
--header="tenant-id: 1"
--header="user-id: 123456"
--header="x-access-token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0ZW5hbnRJZCI6Ijk5OSIsImV4cCI6MTc2MTIwNzkzMCwidXNlcm5hbWUiOiJqaWFuZ3hpYW93ZWkifQ.1r0vVlQGI0GyhpHSi7GGH1_ibtwxBky0Ofrjt9Uy8mo"
http://192.168.0.11:8083/my-test/selectSchedule
参数说明
参数 说明 -t12启动 12 个线程(建议设为 CPU 核数) -c100保持 100 个并发连接 -d30s持续压测 30 秒(可改为 10s快速测试)--header="..."添加请求头(可多次使用) URL 接口地址
等待30s后看到输出内容
Running 30s test @ http://192.168.0.11:8083/jg-platform/selectSchedule
12 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 9.37ms 3.30ms 41.66ms 71.77%
Req/Sec 0.86k 93.45 1.34k 80.64%
308253 requests in 30.02s, 202.84MB read
Requests/sec: 10269.71
Transfer/sec: 6.76MB
wrk压测结果解析
指标 值 分析 Threads 12 多线程并发,压测更真实 Connections 100 保持 100 个长连接 Duration 30.02s 实际运行时间 Total Requests 308,253 30 秒内处理了 30.8 万 请求 Requests/sec (TPS) 10,269.71 每秒处理 1 万 + 请求 Transfer/sec 6.76 MB/s 数据吞吐量健康 Avg Latency 9.37ms 平均延迟极低 Max Latency 41.66ms 最大延迟可控
可以看到此接口压测没有问题,qps = 总请求数/总耗时 = 308,253 /30 = 10,269.71
3、慢接口压测
众所周知,一个水桶的盛水量取决于最短的木板而不是最长的,刚测出的普通的接口能达到1w的qps,还需要测试下最慢的接口,才能更准确的反应系统的真实吞吐量,此次取了一个单机环境下响应时间接近1s的post接口再做压测:
wrk测试post接口需要编辑lua脚本:
-- post_request.lua
wrk.method = "POST"
wrk.headers["Content-Type"] = "application/json"
wrk.headers["tenant-id"] = "1"
wrk.headers["user-id"] = "123456"
wrk.headers["x-access-token"] = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0ZW5hbnRJZCI6Ijk5OSIsImV4cCI6MTc2MTIwNzkzMCwidXNlcm5hbWUiOiJqaWFuZ3hpYW93ZWkifQ.1r0vVlQGI0GyhpHSi7GGH1_ibtwxBky0Ofrjt9Uy8mo"
wrk.body = [[
{
"sectionIds": [
"123456",
"1234567"
],
"tenantId": "1"
}
]]
#开始压测
wrk -t12 -c100 -d30s
-s post_request.lua
http://192.168.0.11:8083/gd-smart/getSectionGroupOneMap
等待30s后输出结果
Running 30s test @ http://192.168.0.11:8083/gd-smart/section/getSectionGroupOneMap
12 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 1.44s 183.57ms 2.00s 76.84%
Req/Sec 3.60 5.16 40.00 78.85%
499 requests in 30.04s, 25.82MB read
Socket errors: connect 0, read 0, write 0, timeout 309
Requests/sec: 16.61
Transfer/sec: 0.86MB
压测结果分析
指标 值 说明 Requests/sec (TPS) 16.61 ⚠️ 极低(之前 GET 是 1w+) Total Requests 499 30 秒只处理了不到 500 个请求 Latency Avg 1.44s 平均延迟高达 1.44 秒 ❌ Latency Max 2.00s 已达到 wrk默认超时阈值Socket errors: timeout 309 ⚡ 309 个请求超时
先说结论:系统没崩,但存在严重性能瓶颈或接口逻辑阻塞
druid连接池监控
这个接口很能反应问题,需要排查,启动druid监控:http://192.168.0.239:18000/druid/login.html


可以看到sql连接池等信息,切换到sql监控排查慢sql:


剩余的就是排查sql问题,该加缓存的加缓存,该加索引的加索引。
4、优化对比
优化前后对比
指标 优化前 优化后 提升 getSectionGroupOneMapQPS30 5000+ 166x getProjectManageListQPS187 1200+ 6.4x 单请求耗时 1.75s <100ms ⬇️ 94% 数据库压力 高 显著降低
5、结语
- 拒绝“能用就行”:前期乱写一时爽,后期维护火葬场
- N+1 查询是性能杀手:尽可能避免循环查 DB
- 善用索引:
WHERE a AND b AND c→ 建立(a,b,c)索引 - Druid 监控:定位慢 SQL,分析sql性能与雷点









