WebSocket本身不提供RPC语义,但可基于其构建轻量级RPC机制:需约定消息格式(含type、id、method、params等字段),客户端维护请求ID映射与超时处理,服务端按method路由执行并原样返回id响应。

WebSocket 本身不提供 RPC(远程过程调用)语义,但可以基于它构建轻量级 RPC 机制:核心是约定请求/响应的消息格式、维护请求 ID 映射、处理超时与错误。关键不在 WebSocket 协议,而在应用层协议设计。
定义统一的 RPC 消息格式
客户端和服务端需协商一套结构化消息格式,通常用 JSON,包含类型、唯一 ID、方法名、参数和可选的返回值或错误信息:
- 请求消息:{ "type": "call", "id": "req_123", "method": "getUser", "params": [101] }
- 成功响应:{ "type": "result", "id": "req_123", "data": { "id": 101, "name": "Alice" } }
- 错误响应:{ "type": "error", "id": "req_123", "code": 404, "message": "User not found" }
type 字段区分消息用途,id 用于关联请求与响应,避免多路并发时混淆。
客户端封装:发送 + 回调管理
在 WebSocket 客户端上封装一个 rpc 方法,内部生成唯一 ID,缓存 Promise 的 resolve/reject,并设置超时:
立即学习“Java免费学习笔记(深入)”;
- 每次调用 rpc('getUser', [101]) 时生成新 id(如 Date.now() + Math.random())
- 将 id → { resolve, reject, timeoutId } 存入 Map(如 pendingCalls)
- 发送请求后,若 10 秒内未收到对应 id 的 result/error,则 clearTimeout 并 reject 超时错误
- onmessage 中检查响应 id,查到则执行对应 resolve 或 reject,并从 Map 中删除
服务端实现:路由 + 执行 + 响应
服务端收到 type: "call" 消息后,根据 method 字段查找注册的函数,执行并返回结果:
- 预先维护一个方法注册表,例如 rpcMethods = { getUser: (id) => db.find(id) }
- 解析请求,校验 method 是否存在、params 类型是否匹配
- 捕获同步/异步执行中的异常,统一包装为 error 响应
- 无论成功或失败,都必须原样带上原始 id 发送 response 类型消息
注意:服务端不维护连接状态映射,只做无状态转发;每个响应必须严格对应请求 id。
健壮性增强点
生产环境建议补充以下机制:
- 序列化/反序列化时使用 try-catch,拒绝非法 JSON
- 限制单条消息大小(如 ≤ 1MB),防止内存溢出
- 为高频调用增加简单限流(如每秒最多 10 次 per connection)
- 心跳保活期间暂停 pendingCalls 的超时计时,断线重连后清空旧 pending
不复杂但容易忽略。


















