Нагрузочное тестирование WebSocket отличается от HTTP-тестирования одним фундаментальным образом: вы измеряете постоянные соединения и пропускную способность сообщений, а не латентность запрос/ответ.
Пример WebSocket в k6
У k6 нативная поддержка WebSocket через модуль k6/ws:
import ws from 'k6/ws';
import { check } from 'k6';
import { Counter, Trend } from 'k6/metrics';
const msgSent = new Counter('messages_sent');
const msgReceived = new Counter('messages_received');
const msgLatency = new Trend('message_latency_ms');
export const options = {
vus: 100,
duration: '2m',
thresholds: {
messages_sent: ['count > 1000'],
message_latency_ms: ['p(95)<200'],
},
};
export default function () {
const url = 'wss://ws.example.com/chat';
const sendTime = {};
const res = ws.connect(url, {}, function (socket) {
socket.on('open', () => {
// Send a ping every second
const intervalId = socket.setInterval(() => {
const id = Date.now().toString();
sendTime[id] = Date.now();
socket.send(JSON.stringify({ type: 'ping', id }));
msgSent.add(1);
}, 1000);
socket.setTimeout(() => {
socket.clearInterval(intervalId);
socket.close();
}, 30000);
});
socket.on('message', (data) => {
const msg = JSON.parse(data);
if (msg.type === 'pong' && sendTime[msg.id]) {
msgLatency.add(Date.now() - sendTime[msg.id]);
delete sendTime[msg.id];
msgReceived.add(1);
}
});
});
check(res, { 'Connected successfully': (r) => r && r.status === 101 });
}
Что измерять
Для WebSocket-тестов стандартные HTTP-метрики не подходят. Смотрите на:
- Скорость установления соединений — сколько соединений в секунду принимает сервер?
- Пропускную способность сообщений — сообщений/с на соединение и суммарно
- Латентность сообщений — время от отправки до получения подтверждения
- Стабильность соединений — сколько соединений обрывается неожиданно?
Масштабирование WebSocket-тестов
Каждый VU в k6 держит открытое соединение. На 1 000 VU нужно 1 000 открытых соединений на машине-генераторе — проверьте ulimit -n перед большими тестами.
Пользователям Perfscale распределённое выполнение автоматически размазывает соединения по нескольким машинам, так что лимит файловых дескрипторов одного хоста перестаёт быть потолком.