压力测试
压测结果受到哪些因素影响?
- 压力机到服务器的网络延迟 (建议内网或本机压测)
- 压力机到服务器的带宽 (建议内网或本机压测)
- 是否开启 HTTP keep-alive (建议开启)
- 并发数是否足够 (外网压测要尽量开启更大的并发)
- 服务端进程数是否合理 (helloworld 业务进程数建议与 cpu 数相同,数据库业务进程数建议为 cpu 的四倍及以上)
- 业务自身性能 (例如是否使用了外网数据库)
HTTP keep-alive 是什么?
HTTP Keep-Alive 机制是一种用于在单个 TCP 连接上发送多个 HTTP 请求和响应的技术,它对于性能测试结果影响很大,关闭 keep-alive 后 QPS 可能成倍下降。 目前浏览器都是默认开启 keep-alive 的,也就是浏览器访问某一个 http 地址后会将连接暂时保留不关闭,下一次请求时复用这个连接,用来提高性能。 压测时建议开启 keep-alive。
压测时如何开启 HTTP keep-alive?
如果是用的 ab 程序压测需要加 - k 参数,例如 ab -n100000 -c200 -k http://127.0.0.1:8787/
。 apipost 需要在返回头中返回 gzip 头才能开启 keep-alive (apipost 的 bug,参考下面)。 其它压测程序一般会默认开启。
为什么通过外网压测 QPS 很低?
外网延迟很大导致 QPS 很低,是正常现象。例如压测 baidu 页面 QPS 可能只有几十。 建议内网或者本机压测,排除网络延迟影响。 如果一定要在外网压测,可以通过增加并发数来增加吞吐量 (需保证带宽充足)。
为什么经过 nginx 代理后性能下降?
nginx 运行需要消耗系统资源。同时,nginx 和 webman 之间的通讯也需要消耗一定的资源。 然而,系统的资源是有限的,webman 无法获取到所有的系统资源,因此,整个系统的性能可能会有所下降是正常现象。 为了尽可能减少 nginx 代理带来的性能影响,可以考虑关闭 nginx 日志 ( access_log off;
), 开启 nginx 到 webman 之间的 keep-alive,参考 nginx 代理。
另外 https 和 http 相比会损耗更多资源,因为 https 需要进行 SSL/TLS 握手,数据加密解密,包的尺寸变大占用更多带宽,这些会导致性能下降。 压测如果用的是短链接 (不开启 HTTP keep-alive),每次请求都需要额外的 SSL/TLS 握手通讯,性能会大幅降低。建议压测 https 开启 HTTP keep-alive。
如何知道系统已经达到性能极限?
一般来说 CPU 达到 100% 时说明系统性能已经达到极限。如果 CPU 还有空闲说明还没达到极限,这时候可以适当增加并发提高 QPS。 如果增加并发无法提高 QPS 则可能是 webman 进程数不够,请适当增加 webman 进程。如果仍然无法提高考虑带宽是否足够。
为什么我压测结果是 webman 性能低于 go 的 gin 框架?
techempower 压测显示 webman 不管在纯文本、数据库查询、数据库更新等所有指标都高于 gin 近一倍左右。 如果你的结果不一样,可能是因为你在 webman 中使用了 ORM 带来了较大的性能损失,可尝试 webman + 原生 PDO 与 gin + 原生 SQL 比较。
webman 中使用 ORM 性能会损失多少?
以下是一组压测数据
环境 服务器阿里云 4 核 4G,本地 MySQL 数据库,从 10 万条记录中随机查询一条数据 json 返回,本机压测。
如果使用原生 PDO webman QPS 为 1.78 万
如果使用 laravel 的 Db::table () webman QPS 降到 0.94 万 QPS
如果使用 laravel 的 Model webmanQPS 降到 0.72 万 QPS
thinkORM 结果类似,区别不大。
提示 虽然使用 ORM 性能会有所下降,但是对于 99% 的业务来说性能已经严重溢出,如果你刚好是那 1% 也可以通过增加 cpu 或者服务器轻松解决。 我们应该在开发效率、可维护性、性能等多个指标中找到一个平衡点,而不是一味追求性能。
为什么用 apipost 压测 QPS 很低?
apipost 的压力测试模块有 bug,如果服务端不返回 gzip 头则无法保持 keep-alive,导致性能大幅下降。 解决办法返回时将数据压缩并添加 gzip 头,例如
<?php
namespace app\controller;
class IndexController
{
public function index()
{
return response(gzencode('hello webman'))->withHeader('Content-Encoding', 'gzip');
}
}
除此之外,apipost 一些情况下无法打出满意的压力,这表现为同样的并发,使用 apipost 要比 ab 低 50% 左右的 QPS。 压测建议用 ab、wrk 或其它专业的压测软件而不是 apipost。
设置合适的进程数
webman 默认开启 cpu*4 的进程数。实际上无网路 IO 的 helloworld 业务压测进程数开成与 cpu 核数一致性能最优,因为可以减少进程切换开销。 如果是带数据库、redis 等阻塞 IO 业务,进程数可设置为 cpu 的 3-8 倍,因为这时需要更多的进程提高并发,而进程切换开销相对与阻塞 IO 则基本可以忽略。
压力测试一些参考范围
云服务器 4 核 4G 16 进程 本机 / 内网压测
- | 开启 keep-alive | 未开启 keep-alive |
---|---|---|
hello world | 8-16 万 QPS | 1-3 万 QPS |
数据库单查询 | 1-2 万 QPS | 1 万 QPS |
压测命令示例
ab
# 100000请求 200并发 开启keep-alive
ab -n100000 -c200 -k http://127.0.0.1:8787/
# 100000请求 200并发 未开启keep-alive
ab -n100000 -c200 http://127.0.0.1:8787/
wrk
# 200 并发压测10秒 开启keep-alive(默认)
wrk -c 200 -d 10s http://example.com