云压测 WebSocket

这篇档提供了在云压测脚本模式中使用 WebSocket 协议进行压测的完整示例。所有示例均基于 pts/ws 模块提供的 WebSocket 连接和消息处理方法。

相关产品
云压测 产品页,含版本规格、价格与购买入口。

一、前置条件

在使用 WebSocket 功能前,请确保:

·导入模块:在脚本开头使用 import ws from 'pts/ws' 导入 WebSocket 模块。

·脚本结构:所有连接和消息处理代码需放在 export default function() 函数中执行。

·URL 格式:确保目标 WebSocket URL 格式正确,支持 ws:// 和 wss:// 协议。

·网络连通性:确保压测环境能够访问目标 WebSocket 服务器。

·理解执行机制:WebSocket 脚本的执行机制与 HTTP 脚本不同:

·HTTP 脚本的每个 VU(虚拟用户)会持续迭代主函数,直到压测结束。

·WebSocket 脚本的每个 VU 不会持续迭代主函数,因为主函数会被 ws.connect 方法阻塞,直到连接关闭。

·在连接建立后的回调函数中,会持续监听和处理异步事件,直到压测结束。

二、注意事项

·连接生命周期:WebSocket 连接建立后,主函数会被阻塞,直到连接关闭。所有业务逻辑都应在 ws.connect() 的回调函数中实现。

·事件监听顺序:应在连接建立后立即注册所有需要的事件监听器,确保不会遗漏任何消息。

·消息发送时机:虽然可以在回调函数的任何位置调用 send(),但应在 open 事件触发后或确认连接已建立后再发送消息。

·资源清理:使用 setTimeout、setInterval 和 setLoop 时,注意在连接关闭时清理这些定时器,避免资源泄漏。

·消息格式:根据服务器要求选择正确的消息格式(文本或二进制),并使用相应的方法发送。

·连接保持:对于长连接场景,建议定期发送 ping 消息或心跳消息,防止连接因超时被关闭。

·并发控制:在压测场景中,每个 VU 会建立独立的 WebSocket 连接,注意控制并发连接数,避免对服务器造成过大压力。

·状态码检查:连接建立后,应检查 res.status 是否为101,确认连接成功建立。

四、函数说明

ws.connect() 用于建立 WebSocket 连接,是 WebSocket 压测的基础方法。该方法在脚本模式的压测场景中使用,支持建立持久连接并进行双向通信。连接建立后,主函数会被阻塞,直到连接关闭。

五、函数签名

ws.connect(url: string, callback: (socket: Socket) => void, headers?: Record<string, string>): Response

六、参数说明

·url (string,必填):目标 WebSocket 服务器的完整 URL 地址,支持 ws:// 和 wss:// 协议。

·callback (function,必填):连接建立成功后的回调函数,接收一个 Socket 对象作为参数。

·回调函数会在连接建立后立即执行。

·在回调函数中定义所有的消息发送和事件监听逻辑。

·回调函数执行完成后,ws.connect 才会返回。

·headers (Record<string, string>,可选):请求连接时的 headers 配置,用于设置自定义请求头。

七、返回值说明

返回 Response 对象,包含以下属性:

·status (number):HTTP 状态码,WebSocket 连接成功时状态码为 101(Switching Protocols)。

·body (string):响应包体内容。

·headers (Record<string, string>):响应头参数。

·url (string):请求地址。

八、使用限制

·URL 必须包含完整的协议前缀(ws:// 或 wss://)。

·回调函数是必需的,所有 Socket 操作都必须在回调函数中进行。

·连接建立后,主函数会被阻塞,直到连接关闭或回调函数执行完成。

·连接失败时,status 不是 101,需要检查连接状态。

十、示例1:基本连接和消息收发

本示例演示如何建立 WebSocket 连接、发送消息和接收消息,适用于基本的 WebSocket 通信场景。

import ws from 'pts/ws';import { check } from 'pts';export default function () { // 建立 WebSocket 连接 const res = ws.connect('ws://mockwebsocket.pts.svc.cluster.local/echo', function (socket) { // 监听连接建立事件 socket.on('open', () => { console.log('WebSocket connected'); }); // 监听接收文本消息事件 socket.on('message', (data) => { console.log('Message received:', data); }); // 监听连接关闭事件 socket.on('close', () => { console.log('WebSocket disconnected'); }); // 发送文本消息 socket.send('Hello, WebSocket!'); }); // 检查连接状态码是否为 101(WebSocket 协议切换成功) check('status is 101', () => res.status === 101);}

十一、示例2:带错误处理的连接

本示例演示如何处理连接错误,适用于需要健壮错误处理的场景。

import ws from 'pts/ws';import { check } from 'pts';export default function () { const res = ws.connect('ws://mockwebsocket.pts.svc.cluster.local/echo', function (socket) { socket.on('open', () => { console.log('Connected successfully'); }); socket.on('message', (data) => { console.log('Received:', data); }); socket.on('close', () => { console.log('Connection closed'); }); socket.send('Test message'); }); // 验证连接成功 check('connection successful', () => res.status === 101); // 连接失败时输出错误信息 if (res.status !== 101) { console.error('Connection failed with status:', res.status); }}

十二、示例3:带自定义请求头的连接

本示例演示如何在建立连接时设置自定义请求头,适用于需要传递认证信息或自定义头部字段的场景。

import ws from 'pts/ws';import { check } from 'pts';export default function () { // 定义自定义请求头 const headers = { 'X-MyApplication': 'PTS', 'X-MyScript': 'WebSocket', 'Authorization': 'Bearer token123' }; // 建立连接并传入 headers const res = ws.connect('ws://mockwebsocket.pts.svc.cluster.local/echo', function (socket) { socket.on('open', () => { console.log('Connected with custom headers'); }); socket.on('message', (data) => { console.log('Received:', data); }); socket.on('close', () => { console.log('Disconnected'); }); socket.send('Hello'); }, headers); check('connection successful', () => res.status === 101);}

十四、函数说明

socket.on() 用于监听 WebSocket 连接的各种事件,是处理异步消息和连接状态变化的核心方法。该方法在 ws.connect() 的回调函数中使用,用于注册事件处理函数。

十五、函数签名

socket.on(event: string, callback: ((…args: any[]) => void)): void

十六、参数说明

·event (string,必填):事件名称,支持以下事件:

·open:建立连接时触发,无参数。

·close:关闭连接时触发,无参数。

·message:接收文本消息时触发,回调函数接收消息内容作为参数。

·binaryMessage:接收二进制消息时触发,回调函数接收 ArrayBuffer 作为参数。

·ping:接收 ping 消息时触发,无参数。

·pong:接收 pong 消息时触发,无参数。

·error:发生错误时触发,回调函数接收错误对象作为参数,错误对象包含 error() 方法用于获取错误信息。

·callback (function,必填):事件回调函数,根据事件类型接收不同的参数。

十七、返回值说明

无返回值(void)。

十八、使用限制

·必须在 ws.connect() 的回调函数中调用。

·同一个事件可以注册多个监听器,都会被执行。

·事件监听器应该在发送消息之前注册,以确保能接收到所有消息。

·message 和 binaryMessage 事件回调函数的参数类型不同,需要根据消息类型选择正确的事件。

20、示例1:监听所有事件类型

本示例演示如何监听 WebSocket 支持的所有事件类型,适用于需要全面监控连接状态的场景。

import ws from 'pts/ws';import { check } from 'pts';export default function () { const res = ws.connect('ws://mockwebsocket.pts.svc.cluster.local/echo', function (socket) { // 监听连接建立 socket.on('open', () => { console.log('Connection opened'); }); // 监听文本消息 socket.on('message', (data) => { console.log('Text message received:', data); }); // 监听二进制消息 socket.on('binaryMessage', (data) => { console.log('Binary message received, length:', data.byteLength); }); // 监听 ping 消息 socket.on('ping', () => { console.log('Ping received'); }); // 监听 pong 消息 socket.on('pong', () => { console.log('Pong received'); }); // 监听连接关闭 socket.on('close', () => { console.log('Connection closed'); }); // 监听错误事件 socket.on('error', (e) => { console.log('Error happened:', e.error()); }); // 发送测试消息 socket.send('Hello'); }); check('connection successful', () => res.status === 101);}

21、示例2:处理不同类型的消息

本示例演示如何区分处理文本消息和二进制消息,适用于需要处理多种消息格式的场景。

import ws from 'pts/ws';import { check } from 'pts';export default function () { const res = ws.connect('ws://mockwebsocket.pts.svc.cluster.local/echo', function (socket) { socket.on('open', () => { console.log('Connected'); // 发送文本消息 socket.send('Text message'); // 发送二进制消息 socket.sendBinary(new ArrayBuffer(8)); }); // 处理文本消息 socket.on('message', (data) => { console.log('Received text:', data); // 可以在这里进行文本消息的业务处理 if (data === 'ping') { socket.send('pong'); } }); // 处理二进制消息 socket.on('binaryMessage', (data) => { console.log('Received binary, size:', data.byteLength); // 可以在这里进行二进制消息的业务处理 const view = new Uint8Array(data); console.log('First byte:', view[0]); }); socket.on('close', () => { console.log('Disconnected'); }); }); check('connection successful', () => res.status === 101);}

23、函数说明

socket.send() 用于向 WebSocket 服务器发送文本消息,是 WebSocket 双向通信中客户端向服务器发送数据的主要方法。该方法在连接建立后的回调函数中使用。

24、函数签名

socket.send(msg: string): void

25、参数说明

msg (string,必填):要发送的文本消息内容。

26、返回值说明

无返回值(void)。

27、使用限制

·必须在连接建立后(open 事件触发后)调用,否则消息无法发送。

·消息内容必须是字符串类型,非字符串值会被转换为字符串。

·连接已关闭时,调用此方法不会报错,但消息不会发送。

·应在 open 事件回调中或确认连接已建立后再发送消息。

29、示例1:发送简单文本消息

本示例演示如何发送简单的文本消息,适用于基本的消息发送场景。

import ws from 'pts/ws';import { check } from 'pts';export default function () { const res = ws.connect('ws://mockwebsocket.pts.svc.cluster.local/echo', function (socket) { socket.on('open', () => { console.log('Connected'); // 连接建立后立即发送消息 socket.send('Hello, Server!'); }); socket.on('message', (data) => { console.log('Echo received:', data); }); socket.on('close', () => { console.log('Disconnected'); }); }); check('connection successful', () => res.status === 101);}

30、示例2:发送 JSON 格式消息

本示例演示如何发送 JSON 格式的文本消息,适用于需要发送结构化数据的场景。

import ws from 'pts/ws';import { check } from 'pts';export default function () { const res = ws.connect('ws://mockwebsocket.pts.svc.cluster.local/echo', function (socket) { socket.on('open', () => { // 构造 JSON 对象并转换为字符串发送 const message = { type: 'chat', user: 'testuser', content: 'Hello from WebSocket', timestamp: Date.now() }; socket.send(JSON.stringify(message)); }); socket.on('message', (data) => { try { // 解析接收到的 JSON 消息 const msg = JSON.parse(data); console.log('Received message:', msg); } catch (e) { console.log('Received non-JSON message:', data); } }); socket.on('close', () => { console.log('Disconnected'); }); }); check('connection successful', () => res.status === 101);}

31、示例3:定时发送消息

本示例演示如何定时发送消息,适用于需要周期性发送数据的场景。

import ws from 'pts/ws';import { check, sleep } from 'pts';export default function () { const res = ws.connect('ws://mockwebsocket.pts.svc.cluster.local/echo', function (socket) { let messageCount = 0; socket.on('open', () => { console.log('Connected, starting to send messages'); }); socket.on('message', (data) => { console.log('Received:', data); }); // 使用 setInterval 定时发送消息 socket.setInterval(function () { messageCount++; const msg = `Message #${messageCount}`; socket.send(msg); console.log('Sent:', msg); }, 1000); // 每秒发送一条消息 // 10 秒后关闭连接 socket.setTimeout(function () { console.log('Closing connection after 10 seconds'); socket.close(); }, 10000); socket.on('close', () => { console.log('Disconnected'); }); }); check('connection successful', () => res.status === 101);}

33、函数说明

socket.sendBinary() 用于向 WebSocket 服务器发送二进制消息,适用于需要传输二进制数据(如图片、文件、协议数据等)的场景。该方法在连接建立后的回调函数中使用。

34、函数签名

socket.sendBinary(msg: ArrayBuffer): void

35、参数说明

msg (ArrayBuffer,必填):要发送的二进制数据,必须是 ArrayBuffer 类型。

36、返回值说明

无返回值(void)。

37、使用限制

·必须在连接建立后调用。

·参数必须是 ArrayBuffer 类型,不能是其他类型(如 Uint8Array、Buffer 等)。

·从其他格式转换为 ArrayBuffer 时,使用 util.toArrayBuffer() 进行转换。

·二进制消息的接收需要使用 binaryMessage 事件,而不是 message 事件。

39、示例1:发送简单二进制数据

本示例演示如何发送简单的二进制数据,适用于基本的二进制消息发送场景。

import ws from 'pts/ws';import { check } from 'pts';export default function () { const res = ws.connect('ws://mockwebsocket.pts.svc.cluster.local/echo', function (socket) { socket.on('open', () => { console.log('Connected'); // 创建一个包含 8 字节的 ArrayBuffer const buffer = new ArrayBuffer(8); const view = new Uint8Array(buffer); // 填充一些测试数据 for (let i = 0; i < view.length; i++) { view[i] = i; } // 发送二进制数据 socket.sendBinary(buffer); console.log('Binary message sent, size:', buffer.byteLength); }); // 监听二进制消息 socket.on('binaryMessage', (data) => { console.log('Binary message received, size:', data.byteLength); const view = new Uint8Array(data); console.log('First 4 bytes:', view.slice(0, 4)); }); socket.on('close', () => { console.log('Disconnected'); }); }); check('connection successful', () => res.status === 101);}

40、示例2:发送字符串转二进制

本示例演示如何将字符串转换为二进制数据发送,适用于需要以二进制格式传输文本的场景。

import ws from 'pts/ws';import { check } from 'pts';import util from 'pts/util';export default function () { const res = ws.connect('ws://mockwebsocket.pts.svc.cluster.local/echo', function (socket) { socket.on('open', () => { // 使用 PTS 的 util.toArrayBuffer 将字符串转换为 ArrayBuffer const text = 'Hello, Binary World!'; const buffer = util.toArrayBuffer(text); socket.sendBinary(buffer); console.log('Sent binary data from string:', text); }); socket.on('binaryMessage', (data) => { // 读取二进制数据的字节信息 console.log('Received binary message, size:', data.byteLength); // 使用 Uint8Array 读取字节 const view = new Uint8Array(data); console.log('First 5 bytes:', Array.from(view.slice(0, 5))); // 将 ArrayBuffer 转换为字符串:使用 base64 编码/解码 // 注意:仅适用于 ArrayBuffer 内容是 UTF-8 编码文本的场景 const base64 = util.base64Encoding(data); const text = util.base64Decoding(base64); console.log('Decoded text:', text); }); socket.on('close', () => { console.log('Disconnected'); }); }); check('connection successful', () => res.status === 101);}

42、函数说明

socket.close() 用于主动关闭 WebSocket 连接,适用于需要控制连接生命周期的场景。调用此方法后,连接会正常关闭,并触发 close 事件。

43、函数签名

socket.close(): void

44、返回值说明

无返回值(void)。

45、使用限制

·可以在连接建立后的任何时候调用

·调用后连接会立即关闭,无法再发送或接收消息

·关闭连接会触发 close 事件

·连接已经关闭时,再次调用此方法不会报错,但不会有任何效果

47、示例1:定时关闭连接

本示例演示如何在指定时间后关闭连接,适用于需要限制连接时长的场景。

import ws from 'pts/ws';import { check } from 'pts';export default function () { const res = ws.connect('ws://mockwebsocket.pts.svc.cluster.local/echo', function (socket) { socket.on('open', () => { console.log('Connected'); socket.send('Hello'); }); socket.on('message', (data) => { console.log('Received:', data); }); // 5 秒后关闭连接 socket.setTimeout(function () { console.log('5 seconds passed, closing connection'); socket.close(); }, 5000); socket.on('close', () => { console.log('Connection closed'); }); }); check('connection successful', () => res.status === 101);}

48、示例2:收到特定消息后关闭

本示例演示如何在收到特定消息后关闭连接,适用于需要根据服务器响应决定是否关闭连接的场景。

import ws from 'pts/ws';import { check } from 'pts';export default function () { const res = ws.connect('ws://mockwebsocket.pts.svc.cluster.local/echo', function (socket) { socket.on('open', () => { console.log('Connected'); socket.send('start'); }); socket.on('message', (data) => { console.log('Received:', data); // 收到 "close" 消息时关闭连接 if (data === 'close' || data === 'bye') { console.log('Received close signal, closing connection'); socket.close(); } else { // 继续发送消息 socket.send('continue'); } }); socket.on('close', () => { console.log('Connection closed'); }); }); check('connection successful', () => res.status === 101);}

50、函数说明

socket.ping() 用于向服务器发送 WebSocket ping 消息,用于保持连接活跃和检测连接状态。服务器通常会响应 pong 消息。该方法在连接建立后的回调函数中使用。

51、函数签名

socket.ping(): void

52、返回值说明

无返回值(void)。

53、使用限制

·必须在连接建立后调用

·ping 消息是 WebSocket 协议层面的控制消息,不会触发 message 事件

·服务器响应 pong 消息时,会触发 pong 事件

·定期发送 ping 可以保持连接活跃,防止因超时被关闭

54、示例:定期发送 Ping 保持连接

本示例演示如何定期发送 ping 消息来保持连接活跃,适用于需要维持长连接的场景。

import ws from 'pts/ws';import { check } from 'pts';export default function () { const res = ws.connect('ws://mockwebsocket.pts.svc.cluster.local/echo', function (socket) { socket.on('open', () => { console.log('Connected'); }); // 监听 pong 响应 socket.on('pong', () => { console.log('Received pong from server'); }); // 每 500 毫秒发送一次 ping socket.setInterval(function () { socket.ping(); console.log('Sent ping'); }, 500); socket.on('message', (data) => { console.log('Received message:', data); }); // 30 秒后关闭连接 socket.setTimeout(function () { console.log('Closing connection'); socket.close(); }, 30000); socket.on('close', () => { console.log('Disconnected'); }); }); check('connection successful', () => res.status === 101);}

56、函数说明

socket.setTimeout() 用于在 WebSocket 连接上设置一个定时器,在指定时间后执行回调函数。适用于需要在特定时间后执行某些操作(如关闭连接、发送消息等)的场景。

57、函数签名

socket.setTimeout(callback: (() => void), intervalMs: number): void

58、参数说明

·callback (function,必填):定时器到期后执行的回调函数,无参数。

·intervalMs (number,必填):定时器延迟时间,单位为毫秒。

59、返回值说明

无返回值(void)。

60、使用限制

·必须在连接建立后的回调函数中调用。

·定时器是单次执行的,执行一次后不会自动重复。

·需要重复执行时,可以在回调函数中再次调用 setTimeout,或使用 setInterval。

·连接在定时器到期前关闭时,定时器不会执行。

62、示例1:延迟发送消息

本示例演示如何使用定时器延迟发送消息,适用于需要延迟操作的场景。

import ws from 'pts/ws';import { check } from 'pts';export default function () { const res = ws.connect('ws://mockwebsocket.pts.svc.cluster.local/echo', function (socket) { socket.on('open', () => { console.log('Connected'); // 2 秒后发送第一条消息 socket.setTimeout(function () { socket.send('First message after 2 seconds'); }, 2000); // 5 秒后发送第二条消息 socket.setTimeout(function () { socket.send('Second message after 5 seconds'); }, 5000); }); socket.on('message', (data) => { console.log('Received:', data); }); // 10 秒后关闭连接 socket.setTimeout(function () { console.log('Closing connection'); socket.close(); }, 10000); socket.on('close', () => { console.log('Disconnected'); }); }); check('connection successful', () => res.status === 101);}

63、示例2:超时自动关闭

本示例演示如何使用定时器实现超时自动关闭连接,适用于需要限制连接时长的场景。

import ws from 'pts/ws';import { check } from 'pts';export default function () { const res = ws.connect('ws://mockwebsocket.pts.svc.cluster.local/echo', function (socket) { let isClosed = false; socket.on('open', () => { console.log('Connected, will close after 5 seconds'); socket.send('Hello'); }); socket.on('message', (data) => { console.log('Received:', data); }); // 5 秒后自动关闭连接 socket.setTimeout(function () { if (!isClosed) { console.log('Timeout reached, closing connection'); isClosed = true; socket.close(); } }, 5000); socket.on('close', () => { console.log('Connection closed'); isClosed = true; }); }); check('connection successful', () => res.status === 101);}

65、函数说明

socket.setInterval() 用于在 WebSocket 连接上设置一个轮询函数,按照指定的时间间隔重复执行。适用于需要周期性执行某些操作(如定期发送消息、定期 ping 等)的场景。

66、函数签名

socket.setInterval(callback: (() => void), intervalMs: number): void

67、参数说明

·callback (function,必填):每次轮询时执行的回调函数,无参数。

·intervalMs (number,必填):轮询间隔时间,单位为毫秒。

68、返回值说明

无返回值(void)。

69、使用限制

·必须在连接建立后的回调函数中调用

·轮询会持续执行,直到连接关闭

·回调函数执行时间超过间隔时间时,会影响定时精度

·应在回调函数中避免耗时操作,或使用异步处理

71、示例1:定期发送消息

本示例演示如何使用轮询函数定期发送消息,适用于需要周期性发送数据的场景。

import ws from 'pts/ws';import { check } from 'pts';export default function () { const res = ws.connect('ws://mockwebsocket.pts.svc.cluster.local/echo', function (socket) { let messageCount = 0; socket.on('open', () => { console.log('Connected, starting periodic messages'); }); socket.on('message', (data) => { console.log('Received:', data); }); // 每 1 秒发送一条消息 socket.setInterval(function () { messageCount++; const msg = `Periodic message #${messageCount}`; socket.send(msg); console.log('Sent:', msg); }, 1000); // 10 秒后关闭连接 socket.setTimeout(function () { console.log('Closing connection'); socket.close(); }, 10000); socket.on('close', () => { console.log('Disconnected'); }); }); check('connection successful', () => res.status === 101);}

72、示例2:定期发送心跳

本示例演示如何使用轮询函数定期发送心跳消息,适用于需要保持连接活跃的场景。

import ws from 'pts/ws';import { check } from 'pts';export default function () { const res = ws.connect('ws://mockwebsocket.pts.svc.cluster.local/echo', function (socket) { socket.on('open', () => { console.log('Connected'); }); socket.on('message', (data) => { console.log('Received:', data); }); // 每 2 秒发送一次心跳消息 socket.setInterval(function () { const heartbeat = { type: 'heartbeat', timestamp: Date.now() }; socket.send(JSON.stringify(heartbeat)); console.log('Sent heartbeat'); }, 2000); // 30 秒后关闭连接 socket.setTimeout(function () { console.log('Closing connection'); socket.close(); }, 30000); socket.on('close', () => { console.log('Disconnected'); }); }); check('connection successful', () => res.status === 101);}

74、函数说明

socket.setLoop() 用于在 WebSocket 连接上设置一个循环执行函数,该函数会持续执行直到连接关闭。与 setInterval 不同,setLoop 的执行频率由函数内部的 sleep() 调用控制,提供了更灵活的执行控制。

75、函数签名

socket.setLoop(callback: (() => void)): void

76、参数说明

callback (function,必填):循环执行的回调函数,无参数。函数内部应包含 sleep() 调用来控制执行频率。

77、返回值说明

无返回值(void)。

78、使用限制

·必须在连接建立后的回调函数中调用

·循环会持续执行,直到连接关闭

·回调函数内部必须调用 sleep() 来控制执行频率,否则会无限快速执行

·建议在回调函数中使用 sleep() 来避免 CPU 占用过高

80、示例 1:循环发送消息

本示例演示如何使用循环函数持续发送消息,适用于需要持续发送数据的场景。

import ws from 'pts/ws';import { check, sleep } from 'pts';export default function () { const res = ws.connect('ws://mockwebsocket.pts.svc.cluster.local/echo', function (socket) { let messageCount = 0; socket.on('open', () => { console.log('Connected, starting loop'); }); socket.on('message', (data) => { console.log('Received:', data); }); // 设置循环,每 0.5 秒发送一条消息 socket.setLoop(function () { messageCount++; socket.send(`Loop message #${messageCount}`); console.log('Sent loop message #' + messageCount); // 必须调用 sleep 来控制执行频率 sleep(0.5); }); // 10 秒后关闭连接 socket.setTimeout(function () { console.log('Closing connection'); socket.close(); }, 10000); socket.on('close', () => { console.log('Disconnected'); }); }); check('connection successful', () => res.status === 101);}

81、示例 2:循环处理业务逻辑

本示例演示如何在循环中处理复杂的业务逻辑,适用于需要持续处理业务的场景。

import ws from 'pts/ws';import { check, sleep } from 'pts';export default function () { const res = ws.connect('ws://mockwebsocket.pts.svc.cluster.local/echo', function (socket) { let state = 'idle'; socket.on('open', () => { console.log('Connected'); state = 'active'; }); socket.on('message', (data) => { console.log('Received:', data); // 根据接收到的消息更新状态 if (data === 'start') { state = 'running'; } else if (data === 'stop') { state = 'stopped'; } }); // 循环处理业务逻辑 socket.setLoop(function () { if (state === 'running') { // 业务逻辑:发送数据 const data = { action: 'process', timestamp: Date.now() }; socket.send(JSON.stringify(data)); console.log('Sent process data'); } else if (state === 'stopped') { console.log('State is stopped, waiting…'); } // 控制循环频率:每 1 秒执行一次 sleep(1); }); // 30 秒后关闭连接 socket.setTimeout(function () { console.log('Closing connection'); socket.close(); }, 30000); socket.on('close', () => { console.log('Disconnected'); state = 'closed'; }); }); check('connection successful', () => res.status === 101);}

82、综合示例:完整的 WebSocket 压测场景

本示例演示一个完整的 WebSocket 压测场景,包含连接建立、消息收发、心跳保持、错误处理和连接关闭等完整流程。

import ws from 'pts/ws';import { check, sleep } from 'pts';export default function () { const res = ws.connect('ws://mockwebsocket.pts.svc.cluster.local/echo', function (socket) { let messageCount = 0; let isActive = true; // 监听连接建立 socket.on('open', () => { console.log('WebSocket connection established'); check('connection opened', () => true); }); // 监听文本消息 socket.on('message', (data) => { messageCount++; console.log(`Message #${messageCount} received:`, data); // 验证消息内容 if (data.includes('echo')) { check('message contains echo', () => data.includes('echo')); } }); // 监听二进制消息 socket.on('binaryMessage', (data) => { console.log('Binary message received, size:', data.byteLength); }); // 监听 pong 响应 socket.on('pong', () => { console.log('Pong received from server'); }); // 监听连接关闭 socket.on('close', () => { console.log('WebSocket connection closed'); isActive = false; }); // 连接建立后立即发送欢迎消息 socket.send('Hello from WebSocket client'); // 定期发送 ping 保持连接 socket.setInterval(function () { if (isActive) { socket.ping(); console.log('Sent ping'); } }, 2000); // 循环发送业务消息 socket.setLoop(function () { if (isActive) { const message = { type: 'data', sequence: messageCount + 1, timestamp: Date.now(), data: `Message content ${messageCount + 1}` }; socket.send(JSON.stringify(message)); console.log('Sent business message:', message.sequence); } sleep(1); // 每 1 秒发送一次 }); // 30 秒后关闭连接 socket.setTimeout(function () { if (isActive) { console.log('Closing connection after 30 seconds'); socket.close(); } }, 30000); }); // 验证连接状态 check('WebSocket connection successful', () => res.status === 101); if (res.status !== 101) { console.error('WebSocket connection failed with status:', res.status); }}

赞 (0)
上一篇 4天前
下一篇 4天前