第25章:性能测试——用Autocannon给信令服务器“上强度”
性能测试这件事,说实话,很多开发者容易忽略。我自己早期做WebRTC项目时,就吃过这个亏。信令服务器在开发环境跑得挺欢,一上线就被用户挤爆了。嗯,从那以后,我养成了一个习惯:上线前必须用Autocannon压一压。
这一章,我们就来聊聊怎么用Autocannon做三件事:压力测试、连接数测试、消息吞吐量测试。说白了,就是看看你的信令服务器到底能扛多少人、能处理多快的消息。
25.1 为什么选Autocannon?
市面上压测工具不少,比如wrk、ab、Siege。但我个人偏爱Autocannon,原因有三:
- Node.js原生支持——信令服务器通常用Node.js写,Autocannon也是Node生态的,集成起来很顺手
- 实时输出——压测过程中能看到实时延迟和吞吐量,不用等跑完才看结果
- 支持WebSocket——信令服务器走的是WebSocket,Autocannon正好支持
25.2 安装与基本用法
安装很简单,一行命令搞定:
npm install -g autocannon
基本用法长这样:
autocannon -c 10 -d 10 http://localhost:3000
这个命令的意思是:10个并发连接,持续压10秒。输出结果会告诉你请求数、延迟、吞吐量等指标。
但注意,这只是HTTP压测。我们要压的是WebSocket信令,所以得用点特殊参数。
25.3 压力测试:看看服务器会不会崩
压力测试的目标很简单:把服务器压到极限,看它什么时候扛不住。我一般会从低并发开始,逐步往上加,直到服务器出现错误或延迟飙升。
先写一个简单的WebSocket信令服务器(假设你已经有了,这里只给压测脚本):
// 压测脚本:压力测试
const autocannon = require('autocannon');
const instance = autocannon({
url: 'ws://localhost:3000/signaling',
connections: 100, // 并发连接数
duration: 30, // 持续30秒
ws: true, // 启用WebSocket模式
messages: [
{
message: JSON.stringify({ type: 'join', room: 'test' }),
onMessage: (data) => {
// 收到响应后继续发下一条
return JSON.stringify({ type: 'message', content: 'hello' });
}
}
]
});
autocannon.track(instance);
跑起来之后,你会看到类似这样的输出:
| 指标 | 说明 | 健康值参考 |
|---|---|---|
| Latency (平均) | 消息往返延迟 | < 50ms |
| Requests/sec | 每秒处理请求数 | 越高越好 |
| Errors | 错误数(超时、断开等) | 0 |
| Throughput | 吞吐量(MB/s) | 视带宽而定 |
25.4 连接数测试:到底能撑多少人?
连接数测试,说白了就是看服务器能同时维持多少WebSocket连接。WebRTC场景下,每个用户至少占一个信令连接,所以这个指标直接决定了你的系统能支持多少用户同时在线。
我习惯用阶梯式加压:
// 连接数测试:阶梯式加压
const runTest = async (connections) => {
console.log(`正在测试 ${connections} 个连接...`);
const result = await autocannon({
url: 'ws://localhost:3000/signaling',
connections: connections,
duration: 10,
ws: true,
// 只建立连接,不发消息
messages: []
});
console.log(`连接数: ${connections}, 错误率: ${result.errors}%`);
};
// 从100开始,每次加100,直到2000
for (let i = 100; i <= 2000; i += 100) {
await runTest(i);
}
跑完之后,你会得到一个表格:
| 并发连接数 | 错误率 | 平均延迟 | 结论 |
|---|---|---|---|
| 100 | 0% | 12ms | 轻松 |
| 500 | 0% | 18ms | 正常 |
| 1000 | 0.5% | 45ms | 开始吃力 |
| 1500 | 3% | 120ms | 接近极限 |
| 2000 | 15% | 350ms | 已过载 |
25.5 消息吞吐量测试:消息能跑多快?
连接数只是基础,消息吞吐量才是信令服务器的核心能力。WebRTC场景下,信令消息包括:加入房间、离开房间、ICE候选、SDP交换等。如果消息处理慢了,用户就会感觉卡顿。
消息吞吐量测试,我一般这样设计:
// 消息吞吐量测试
const autocannon = require('autocannon');
const instance = autocannon({
url: 'ws://localhost:3000/signaling',
connections: 50, // 固定50个连接
duration: 60, // 持续60秒
ws: true,
messages: [
{
message: JSON.stringify({ type: 'join', room: 'test' }),
onMessage: (data) => {
// 收到join响应后,立即发送ICE候选
return JSON.stringify({ type: 'ice_candidate', candidate: '...' });
}
},
{
message: JSON.stringify({ type: 'ice_candidate', candidate: '...' }),
onMessage: (data) => {
// 收到ICE响应后,发送SDP
return JSON.stringify({ type: 'sdp_offer', sdp: '...' });
}
}
]
});
autocannon.track(instance);
这里的关键是消息链:每条消息的发送依赖于上一条消息的响应。这样模拟出来的场景更接近真实情况。
输出结果中,我最关注两个指标:
- 消息/秒——服务器每秒能处理多少条信令消息
- 延迟分布——P50、P95、P99延迟,看有没有长尾
25.6 性能测试的核心流程
说了这么多,我画了一张图帮你理清思路:
25.7 避坑指南
最后,分享几个我踩过的坑:
- 不要在本机压本机——我曾经用同一台机器既跑服务器又跑压测,结果CPU打满,数据完全失真。最好用两台机器,或者至少用不同端口。
- 注意文件描述符限制——Linux默认每个进程只能打开1024个文件描述符。如果你要压2000个连接,记得先执行
ulimit -n 4096。 - WebSocket的keep-alive——有些信令服务器会主动断开空闲连接。压测时如果消息间隔太长,连接会被断开,导致错误率虚高。可以在消息链里加一个心跳消息。
- 结果要多次取平均——网络抖动、GC暂停都会影响单次结果。我一般每个场景跑3次,取中位数。
公众号:蓝海资料掘金营,微信deep3321