性能评测的第一步不是急着运行wrk,而是明确要回答的问题:这台DigitalOcean云主机上的Web服务最大能扛住多少请求,延迟在什么水平,瓶颈出现在哪一层。wrk适合做这类快速基准测试,因为它不像ApacheBench那样受单线程模型限制,也不像JMeter那样依赖较重Java运行时。把wrk部署在DigitalOcean Droplet上,可以低成本获得可重复的压测结果。

一、为什么选wrk在DigitalOcean上做压测
DigitalOcean Droplet按小时计费、规格固定,特别适合搭建临时压测环境。同一个测试可以在相同CPU、内存和磁盘配置下重复执行,减少环境差异带来的干扰。wrk本身是一个轻量的HTTP基准测试工具,它使用多线程加事件驱动模型,单台机器就能打出很高的并发请求,不需要额外部署复杂的集群。
与常用的ab相比,wrk的优势在于多线程和高效的epoll事件循环。ab默认使用单线程处理请求,遇到高并发场景容易把客户端自身的CPU或线程调度变成瓶颈。JMeter功能全面,但Java运行时消耗大量内存,启动慢,动态脚本编写也不够轻便。wrk的Lua脚本扩展能力则可以在不修改源码的情况下模拟带参数请求、自定义请求头、构造POST请求体等场景。
在DigitalOcean上选wrk还有一层实际考虑:Droplet的CPU配额和网络带宽是有限的,压测工具本身要尽量少占用资源,把更多CPU留给被测服务。wrk消耗的资源比JMeter少得多,更容易在较小规格的Droplet上测出被测程序自身的表现。
二、在DigitalOcean上安装wrk
建议新建一台Ubuntu 22.04 LTS的Droplet,规格至少为2 vCPU、4GB内存。如果压测目标和wrk在同一台机器上运行,需要预留一部分CPU给被测服务,否则压测工具会和被测服务争抢资源,导致结果偏低。如果条件允许,最好把wrk和被压测的Web服务分别放在同一VPC网络内的两台Droplet上,用内网IP访问。
Ubuntu的仓库里虽然也可以直接安装wrk,但版本通常较旧,部分新特性不支持。推荐从源码编译,过程并不复杂。先安装编译依赖,然后克隆仓库并编译:
sudo apt update && sudo apt install -y build-essential libssl-dev git git clone https://github.com/wg/wrk.git cd wrk make sudo cp wrk /usr/local/bin wrk --version
编译完成后,wrk --version能打印版本号就说明安装成功。如果压测的是HTTPS接口,需要保证系统里装有OpenSSL开发库,libssl-dev已经在上面安装。后续如果需要自定义Lua脚本,还可以安装LuaJIT开发包,不过大多数基础压测场景用不到。
三、设计压测场景与参数
wrk的基础命令格式是wrk [选项] URL。最常用的选项包括线程数、连接数和持续时间。下面是一个针对本地回环地址的压测示例:
wrk -t4 -c100 -d30s --latency http://127.0.0.1:8080/
上面的命令会启动4个线程,维持100个HTTP连接,持续压测30秒,并在最后输出延迟分布。各参数含义如下表:
| 参数 | 作用 |
|---|---|
-t | 压测线程数,一般设置为CPU核心数的1到2倍 |
-c | 保持的HTTP连接总数,连接数越高压力越大 |
-d | 压测持续时间,例如10s、30s、60s |
--latency | 输出50%、75%、90%、99%等延迟分位数 |
-s | 加载Lua脚本,用于模拟复杂请求 |
压测本地回环地址可以排除公网网络波动的影响,先确认服务端在理想网络条件下能达到什么水平。得到基线数据后,再通过VPC内网地址测试真实网络开销。直接用公网IP压测最容易得到偏差很大的结果,因为DigitalOcean Droplet的公网带宽和延迟并不稳定,且会消耗宝贵的公网流量配额。
如果要模拟带请求体的POST接口,可以写一个简单的Lua脚本,让每次请求都发送JSON数据:
wrk.method = "POST"
wrk.headers["Content-Type"] = "application/json"
wrk.body = '{"query":"test"}'
将脚本保存为post.lua,然后在压测命令中加入-s post.lua即可。对于需要随机参数的GET接口,也可以构造动态URL,避免缓存导致压测数据虚高。
四、读懂压测报告并定位瓶颈
一次完整的wrk输出大致如下:
Running 30s test @ http://127.0.0.1:8080/
4 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 35.20ms 12.44ms 210.30ms 82.16%
Req/Sec 2.84k 420.22 3.98k 72.00%
Latency Distribution
50% 32.10ms
75% 40.20ms
90% 55.30ms
99% 120.00ms
339648 requests in 30.10s, 81.20MB read
Requests/sec: 11284.11
Transfer/sec: 2.70MB
报告中的Avg是平均延迟,Stdev是标准差,Max是最大延迟,+/- Stdev表示延迟落在平均值正负一个标准差范围内的请求占比。延迟分布比平均值更重要,尤其是99%分位数,它反映了接近最坏情况下的用户体验。如果99%延迟明显高于90%延迟,说明存在少量慢请求,可能的原因包括GC停顿、锁竞争、磁盘IO抖动或外部依赖超时。
Requests/sec表示每秒完成的请求数,这是吞吐量的核心指标。Transfer/sec表示每秒传输的数据量,对静态文件服务尤其有参考价值。判断瓶颈时要结合CPU使用率、内存使用率和网络流量。如果CPU已经接近100%,吞吐量却上不去,优先考虑扩容或优化应用逻辑。如果CPU使用率不高但延迟很高,可能是连接数不足、线程阻塞或数据库连接池耗尽。
在DigitalOcean Droplet上可以使用htop、ss -s等命令快速查看资源使用情况:
htop ss -s tail -f /var/log/nginx/error.log
如果压测的是Nginx反向代理后的应用,还可以查看Nginx访问日志和错误日志,结合响应状态码判断失败请求是发生在代理层还是后端。大量499状态码通常意味着客户端断开连接,往往是后端响应太慢导致。
五、DigitalOcean环境下的避坑与优化
在DigitalOcean上压测最常被忽略的问题是网络类型。公网IP的带宽和延迟都不适合做精确基准测试,尤其是小规格Droplet的公网带宽按CPU核心数分配,很容易先撞上带宽上限。解决方法是改用VPC内网地址,或者直接把测试目标绑定到127.0.0.1进行回环测试。内网带宽通常远高于公网带宽,能更准确反映服务端的处理能力。
另一个常见的瓶颈是文件描述符数量。高并发连接会占用大量文件描述符,如果系统默认限制太低,wrk或Nginx会在连接数达到一定值后报错。可以临时调整限制并优化内核参数:
ulimit -n 65535 sysctl -w net.ipv4.ip_local_port_range="1024 65000" sysctl -w net.core.somaxconn=1024
这些参数调整只对当前会话或临时生效,需要持久化可以写入/etc/security/limits.conf和/etc/sysctl.conf。需要注意的是,文件描述符和内核参数的调整要结合Droplet的实际内存和CPU资源,不要把连接数调得过高,否则可能引发内存不足或内核软中断占用过高。
应用层也要配合优化。以Nginx为例,worker_processes可以设置为auto,keepalive_timeout适当延长,以减少频繁建立TCP连接的开销。对于静态资源,可以开启sendfile和gzip。如果后端是PHP、Node.js或Go应用,要分别检查进程数、事件循环阻塞和数据库连接池配置。用wrk的Lua脚本模拟随机请求也是避免缓存导致数据虚高的有效办法:
request = function()
local id = math.random(1, 10000)
return wrk.format("GET", "/items/" .. id)
end
最后要记住,单次压测结果只能作为参考。建议在同一配置下重复测试多次,去掉明显异常值后再取平均。DigitalOcean Droplet的邻居噪声和底层虚拟化调度都有可能影响数据,持续压测时间不宜过短,一般建议至少30秒到60秒,让服务进入稳定状态后再采信结果。
DigitalOceanwrkWeb性能评测修改时间:2026-08-26 03:23:51