以前我一直觉得Postman 测 WebSocket 是个“伪需求”。HTTP 接口用 Postman 顺手得很WebSocket 这种长连接、双向推送的东西随便开个网页控制台或者写几行 Node 脚本不就完事了吗直到后来真负责了一个实时消息服务的接口测试才发现控制台只能验证“通不通”根本撑不起“协议对不对、心跳稳不稳、异常能不能恢复”这类正经测试需求。而 Postman 从很早的版本就开始支持 WebSocket 请求只是很多人把它当普通 HTTP 工具用压根没注意过这个入口。这篇文章就用实际项目的视角聊聊怎么用 Postman 把 WebSocket 接口从连接到压测再到异常排查完整地测起来。不管你是后端开发、测试工程师还是偶尔要联调的运维只要能看懂 HTTP 接口测试这套思路和操作你都能直接照着用。1. 先搞清楚WebSocket 接口到底要测什么很多人的第一反应是WebSocket 接口不就是“建立连接、发消息、收消息”嘛能连上不就完事了真这么想基本会在第一个生产事故面前翻车。因为 WebSocket 接口的核心难点从来不是“连上”而是连接建立之后的一整套状态管理。1.1 HTTP 和 WebSocket 的本质差异为什么要换一套测试思路HTTP 是“你问一句我答一句”的短连接模型。客户端发一个请求服务端回一个响应这个交互就结束了连接随之关闭或复用。测试 HTTP 接口时你关心的是“返回啥、状态码多少、响应时间多长”核心是请求-响应的配对关系。WebSocket 完全不是这个思路。它先通过 HTTP 完成一次握手将协议升级为 WebSocket之后客户端和服务端之间就建立了一条全双工的长连接。这意味着服务端可以主动推送消息客户端没有请求也会收到数据。连接一旦建立可以保持几秒、几分钟甚至几小时。连接期间可能穿插着心跳、重连、鉴权失效、消息乱序等情况。所以测 WebSocket 接口不能沿用“发一个请求看一个响应”的线性思维而是要把它当成一个有生命周期的会话来测试。你需要验证的不是某一帧消息而是连接建立、消息交互、保活、断开、重连这条完整链路。1.2 哪些场景必须用 WebSocket 测试哪些场景用它反而是浪费用 Postman 测 WebSocket 真正合适的场景我认为有三类协议联调阶段前后端约定好消息格式但服务端还没完全实现好。用 Postman 可以手动模拟各种客户端行为验证服务端在边界情况下的表现。接口回归验证改完服务端代码需要快速确认 WebSocket 的核心流程没被搞坏。保存成 Collection 后一键重跑效率远高于手工开网页。问题复现与排查线上出现“连接被踢”或者“消息收不到”的问题用 Postman 模拟相同参数和环境可以快速缩小排查范围。但如果你要测的是高并发下的连接稳定性或者长时间的多连接场景Postman 就不合适了。它本质上是单连接、人工交互的调试工具压测还是得交给专业工具或自己写脚本。这一点提前说清楚免得你选错工具耽误事。2. 测试前的环境与参数准备磨刀不误砍柴工。WebSocket 测试的准备工作看起来不多但每一项都直接影响你能不能顺利连上、消息能不能看懂。2.1 版本与界面用对工具才能少踩坑首先确认你的 Postman 版本。WebSocket 支持功能从 8.x 版本开始就陆续完善了建议直接用最新版或者至少是最近一两年内的版本。老版本有两个硬伤一是连接管理不稳定二是脚本能力缺失。我曾经在 7.x 版本里连一个本地 WebSocket 服务明明服务端日志显示握手成功了Postman 界面却一直转圈换成新版本立刻正常。新版 Postman 创建请求时主界面会直接出现 “WebSocket Request” 入口不用额外装插件也不用开什么内测开关。这一点对国内用户很友好不用费劲折腾安装过程。2.2 连接 URL 的构成别只盯着 ws:// 和 wss://WebSocket 的 URL 格式是ws://host:port/path?query wss://host:port/path?queryws对应明文HTTPwss对应加密的HTTPS。生产环境基本全是wss本地开发大多是ws。有个小细节是路径很多 WebSocket 服务的路径不是根路径可能是/ws、/socket、/live之类的这个一定要跟服务端开发确认清楚光有 host 和 port 不一定能连上。查询参数也非常值得注意。有些接口的鉴权信息是通过 URL 参数传的比如wss://api.example.com/ws?tokeneyJhbGciOi...这种情况下Postman 的 URL 输入框要完整带上 query否则握手阶段就会被服务端拒掉。另一个很少有人提到的点Cookie。某些业务会把会话标识放在 Cookie 里握手时浏览器会自动带上但 Postman 默认不会自动携带浏览器 Cookie。如果服务端依赖这个做身份识别你需要在头部手动添加 Cookie 字段否则会出现“握手成功但连接马上被关闭”的诡异现象。2.3 环境变量与多环境隔离从第一天就养成的习惯我见过太多人把 WebSocket 地址硬编码在 URL 输入框里本地测完改成测试环境地址测完再改成生产地址来回复制粘贴。这做法在接口少的时候没问题一旦你有多个服务、多套环境管理起来就是灾难。推荐的做法是从一开始就用环境变量在 Postman 里配置一套环境比如Dev、Test、Prod每个环境定义ws_base_url、ws_token等变量。URL 输入框写成{{ws_base_url}}/ws。鉴权头写成Authorization: Bearer {{ws_token}}。这样切换环境时只需要在右上角下拉框切换剩下的全部自动生效。不只是 WebSocket 请求所有 HTTP 请求也用同一套变量整个项目都清爽很多。3. 从握手到收发消息核心操作全流程这部分是实战重点。我按“建立连接 → 发送接收消息 → 带鉴权 → 心跳保活”的顺序一步步拆每一步都解释这么做的原因顺便把踩过的坑标出来。3.1 建立连接握手参数别乱填也别不填新建 WebSocket 请求后第一件事是填 URL第二件事是检查 Headers 区域。敲黑板这个 Headers 可不是你想象中“随便填”的普通请求头它是握手时发送给服务端的 HTTP 头部直接影响服务端认不认你这个客户端。握手阶段至少要理解这几个头的含义Header说明必须吗Connection: Upgrade告诉服务端我要协议升级是Postman 自动带Upgrade: websocket升级目标协议是Postman 自动带Sec-WebSocket-Key客户端生成的随机 key服务端据此计算响应是Postman 自动带Sec-WebSocket-Version协议版本默认 13是Postman 自动带Sec-WebSocket-Protocol子协议协商比如chat或mqtt按需填Authorization/Cookie等业务鉴权按需填注意Sec-WebSocket-Protocol的用法它不是随便填的必须填服务端支持的子协议名称否则服务端可能直接拒绝握手。比如你用 STOMP 协议的服务子协议就要写v12.stomp之类的具体值。子协议不匹配时服务端要么不响应要么返回错误状态这个下文排查部分会讲。点击 “Connect” 按钮后如果一切正常界面的连接状态会变成绿色消息区域出现连接成功的信息。此时有个常被忽略的点连接成功后不要立刻关掉窗口。Postman 的 WebSocket 请求在连接状态下可以持续观察关掉编辑器就等于断开连接。我习惯把连接窗口保持住同时在服务端日志里能看到一个稳定的 session。3.2 发送与接收消息文本、JSON、二进制一次讲清连接建立后消息输入框就亮了。这里最大的误区是把消息框当成“命令行”随手敲一堆不规范的文本。实际接口联调时消息格式必须跟服务端对齐否则对方解析失败你还会以为是连接的问题。先聊最常见的 JSON 消息。约定一个格式比如{ type: subscribe, topic: price.btc.usdt }发送后服务端可能返回{ type: subscribe_ack, topic: price.btc.usdt, status: ok }这种一问一答你直接在 Postman 下方消息列表里就能看到往返记录。界面左右两侧分别是发送和接收的消息时间线清晰比自己在控制台打日志要直观得多。如果你测的是实时推送类接口服务端可能每秒推送 N 条消息。这时候建议先不要急着看每一条内容而是整体观察消息是否连续不断有没有突然的空档消息结构是否一致有没有偶尔出现缺字段的情况推送频率是否符合服务端配置比如固定 1s 推一次结果变成 5s 推一次这就是问题。二进制消息是另一个容易卡住的点。Postman 默认支持发送文本但有些实时协议如部分游戏、音视频信令场景用二进制帧传输。Postman 在消息输入框支持选择 payload 类型可以切换到二进制输入。不过坦白说二进制消息的可读性非常差真正调试时我反而用专门的工具或者让开发先把二进制协议加上十六进制打印日志再回到 Postman 里比对握手和基本流程。3.3 带鉴权的 WebSocket 连接几种常见做法现实中的业务接口几乎不会让你裸连。WebSocket 鉴权常见有四种Postman 完全可以覆盖第一种URL 参数携带 token。前面提到过直接在 URL 里加?tokenxxx。这种方式在浏览器地址栏都会被记录安全性一般但很多老系统还在用。Postman 里直接把完整 URL 填进去即可。第二种握手 Header 携带 token。这是最常见的做法在 Headers 里加Authorization: Bearer token。注意这个 token 一般跟你调用 HTTP 接口的 token 是同一套身份体系但很多服务端对 WebSocket 的 token 校验策略更严格。同样是过期时间 30 分钟的 tokenHTTP 接口可能只在校验时才读取而 WebSocket 建立后可能要求定时重鉴权或者连接建立后立刻校验一次。我遇到过服务端在 WebSocket 建立后 5 秒内没收到“鉴权确认”消息就主动断开的情况这种业务逻辑就得靠下面说的消息交互来模拟。第三种子协议携带。少数服务端通过Sec-WebSocket-Protocol字段传身份标识比如Authorization子协议。做法是在握手头里设置Sec-WebSocket-Protocol: mytoken.实际值。很怪但确实存在。第四种先 HTTP 获取身份再动态拼进 WebSocket。这是最流程化也最实用的场景。比如你先要调用/login拿到一个临时 token然后带着这个 token 去开 WebSocket。Postman 里有两种用法手动法先把/login请求跑一遍从响应里复制 token再粘贴到 WebSocket 请求里。适合临时调试。自动法在 WebSocket 请求的 Pre-request Script 里写脚本先发一个 HTTP 请求把返回的 token 写入环境变量然后 URL 或头部引用这个变量。自动法具体怎么写下文脚本部分会展开。3.4 心跳机制模拟服务端没踢你不代表连接健康心跳是 WebSocket 测试里最容易被忽略、也很影响生产稳定性的一环。很多服务的连接超时时间不长比如 60 秒内没有收到客户端任何消息服务端就会主动断开。设计合理的心跳机制其实是客户端和服务端之间的“默契约定”。用 Postman 测心跳先要搞清楚两件事服务端的心跳协议是什么有的用ping/pong控制帧有的用业务消息{ type: heartbeat }有的干脆要求客户端每隔 30 秒发任意消息就算活跃。服务端断开策略是什么超过多久没收到消息才会断开我建议按以下步骤测连接成功但什么都不发观察多久被服务端断开。记录断开时间这就是最短空闲阈值。每隔 20 秒发送一次心跳消息观察连接是否长时间稳定。如果稳定说明心跳策略生效。再换一个更长的间隔比如 90 秒观察服务端是否踢人。这一步能测出服务端“容忍度”是否跟文档一致。如果服务端的心跳是基于控制帧ping/pongPostman 的普通消息框不一定能直接发送 ping 帧。这种情况我通常用脚本层的 WebSocket API 处理或者直接用一段小脚本模拟下文第 4 部分会给出一个参考实现。手动测心跳的意义在于你至少要知道“多久不发会被踢”不然客户端写得再花哨服务端那边根本不认连接一样说断就断。4. 进阶玩法脚本、动态参数与自动化断言如果你只把 Postman 当“手动发消息的工具箱”那确实有点浪费。WebSocket 请求同样支持 Postman 的脚本能力这才是把“临时调试”变成“自动化验证”的关键分水岭。4.1 用脚本在连接前后注入逻辑Postman 的 WebSocket 请求脚本区域提供了一组核心事件你可以在里面写 JavaScript控制整个连接生命周期事件触发时机典型用途pm.websocket.onopen连接建立成功后记录日志发送初始化消息pm.websocket.onmessage收到任意消息时解析消息执行断言pm.websocket.onerror发生错误时打印错误信息统计错误次数pm.websocket.onclose连接关闭时记录关闭码判断是否为预期断开举个例子我测试一个实时行情推送服务时需要在连接建立后自动订阅频道并对每一条推送做结构校验。脚本可以这样写pm.websocket.onopen function () { console.log(连接成功开始订阅); pm.websocket.send(JSON.stringify({ type: subscribe, topic: price.btc.usdt })); }; pm.websocket.onmessage function (message) { const data JSON.parse(message); pm.test(推送消息包含交易对字段, function () { pm.expect(data).to.have.property(symbol); pm.expect(data.symbol).to.eql(btcusdt); }); }; pm.websocket.onclose function (code, reason) { console.log(连接关闭, code, reason); };这里有个关键点pm.test在 WebSocket 的onmessage里也能用。这意味着你可以对 WebSocket 的推送做自动化断言而不是每次肉眼检查。连接跑起来之后只要消息结构有问题测试面板就会直接标红肉眼不再需要盯每一帧消息。另外一个细节是脚本里发送消息时先确认服务端已经初始化完成。有些服务端在握手后要 1-2 秒做好内部资源分配你立刻发订阅消息可能被丢弃。稳妥的做法是在onopen里加一个小延迟const timer setTimeout(function () { pm.websocket.send(JSON.stringify({ type: subscribe, topic: test })); }, 1000);这个延迟时间需要根据服务端实际表现调整没有固定标准但实测下来比“连上就发”成功率高很多。4.2 对 WebSocket 消息做自动化断言很多测试同学觉得 WebSocket 没法在 Postman 里写断言只能靠人工看。这个观念该更新了。onmessage里不仅能打日志还能跑完整的pm.expect断言体系。实际项目里最常用的三类断言结构校验推送的消息必须包含哪些字段字段类型对不对。针对接口中data字段经常某次突然变成null的问题断言能立刻发现。数值范围例如推送的价格必须是正数时间戳不能是过去时间等等。事件顺序比如必须subscribe_ack先返回然后才推送具体数据。这一点用脚本可以做简单状态机判断。我用这套方式跑过不下十几个 WebSocket 场景省下的人工核对时间非常可观。特别是那种一秒推送很多条数据的接口人工盯着屏幕看十分钟眼睛都要花而脚本可以在消息到达的瞬间完成所有检查还顺便把测试结果留在 Postman 的报告里。4.3 把 WebSocket 请求纳入自动化与 CI/CD 的注意点这里必须说一个很多人不知道的坑Postman 的 Newman 命令行工具对 WebSocket 请求的支持非常有限我印象中 Newman 并不会像执行普通 HTTP 请求那样完整执行 WebSocket 请求。也就是说你在 Postman 图形界面里跑得好好的用例newman run collection.json一跑WebSocket 部分的执行效果可能会大打折扣。所以我对 WebSocket 自动化的建议是分两步走在 Postman 里把 WebSocket 连接的验证步骤和脚本写好特别是握手、订阅、鉴权这些前置步骤保证手动一键可复现。自动化回归时把 WebSocket 请求与普通 HTTP 请求分开处理。HTTP 部分照常用 Newman 接入 CI/CDWebSocket 部分写一个轻量脚本Node 的ws库或者 Python 的websockets库在 CI 里单独跑。这样既享受了 Postman 图形化调试的便利也不至于在自动化阶段被工具的限制卡住。5. 常见问题与排查技巧实录WebSocket 测试里遇到的报错跟 HTTP 那种明确的 4xx/5xx 不太一样很多错误码看起来让人摸不着头脑。我整理了一份速查表再挑几个真实案例说一下排查思路。5.1 连接类问题握手失败、1006、超时现象可能原因处理建议握手返回 401/403鉴权失败检查 token 是否过期Header 是否写对是否漏了 Cookie握手返回 404路径不对确认 WebSocket 路径是否多了或少了一层连接状态立刻变成 1006异常关闭非正常握手流程看服务端日志多数是鉴权未通过或子协议不匹配一直 CONNECTING 然后超时网络不通或服务端未监听换个工具用命令行确认端口连通性连接成功但马上断开服务端要求客户端尽快发首包在onopen里补发初始化消息1006是 WebSocket 协议里很特殊的一个错误码它表示连接异常关闭但没有收到关闭帧。出现这个码优先级最高的事情不是猜而是去服务端日志看有没有握手阶段的报错。我见过太多人对着 1006 排查半天结果发现是服务端代码里对 token 做了严格校验握手成功后直接ctx.close()。5.2 消息类问题收不到、乱码、顺序不对收不到消息这个问题比连接失败还让人头疼因为连接状态明明是好的。常见原因有订阅动作没发出去或者订阅格式跟服务端预期不一致。服务端没有报错但也没把你加进订阅列表。你监听的消息频道跟服务端推送的频道不一致。比如订阅的是price.btc.usdt服务端推的是price.btcusdt一个字符差异就能让消息失联。服务端推送的是二进制帧Postman 的消息区默认按文本解析显示出来就是乱码或者空内容。乱码问题建议先看 Postman 是否能区分文本帧和二进制帧。如果确认是二进制就在服务端确认编码方式再考虑用脚本里的 ArrayBuffer 解析逻辑。消息顺序不对的情况常见于多服务器节点场景比如服务端有多个实例客户端连的节点跟推送的节点不同导致消息乱序或重复。这个不好在客户端侧简单解决但 Postman 可以用来确认“消息是不是真的乱序了”帮开发那边定位集群配置问题。5.3 一个真实排查案例客户端连接正常但收不到订阅消息分享一个印象很深的案例。某个交易平台的数据推送服务客户端接入时能成功握手也能正常发送文本消息但就是收不到主动推送。服务端开发说推送逻辑没问题客户端开发说订阅消息发得没问题两边僵住了。我用 Postman 复现了一遍完整流程建立连接后先发一条普通chat类型的消息服务端正常返回然后发订阅消息发现服务端毫无反应。继续翻服务端日志发现一条业务级的 warning订阅主题的格式在最近一次迭代中加了前缀老客户端没升级所以订阅失败。问题不在于 WebSocket 连接而在于业务协议版本不匹配。这种问题你在浏览器控制台里也能发现但 Postman 的价值在于它能把握手状态和消息交互分开观察快速定位到是“连接层面”还是“业务消息层面”出了问题省得两方开发互相甩锅。5.4 顺手把 WebSocket 请求保存成 Collection 的细节连接调试通过后千万别关掉窗口就完事。把请求命名清楚保存到 Collection 里这是很多资深测试的习惯也直接影响后续回归效率。命名时建议带上场景关键词比如WebSocket-行情订阅-正常路径WebSocket-心跳-60s不发消息断开WebSocket-鉴权-过期token这比叫test1、test2好一万倍。我见过项目里 Collection 里上百个请求全是New Request翻到崩溃也没人敢删。最后说一个个人习惯每次用 Postman 测 WebSocket 接口我都会先抓一次服务端的成功握手日志和断开日志确认“正常长什么样”。有了这个基准后面再怎么折腾至少心里有底。你如果一开始连“正常”都没见过那后面所有的现象都是“异常”排查起来只会越陷越深。工具只是工具真正值钱的是对整个协议交互过程的理解。把 Postman 用熟只是第一步更重要的是借着每一次连接失败把 WebSocket 的握手、心跳、消息帧和断连机制彻底吃透。等你能不看文档就预判服务端下一步会干什么的时候这个接口在你眼里就没有秘密了。
阅读完成 · 觉得有帮助?