WebSocket close code 1006 为何没有服务端原因
浏览器里看到 WebSocket close code 1006,却发现 event.reason 是空字符串,服务端也没有“主动关闭”的记录,这并不表示服务端漏写了原因。1006 是 WebSocket 规范保留的异常关闭表示:连接结束时没有收到 Close 帧,浏览器只能告诉你“连接非正常结束”,不能凭这个数字还原真正的故障原因。
排查时要把客户端事件、反向代理连接日志和应用日志放在同一条时间线上。只有应用确实发出了 Close 帧,客户端才能拿到对应的状态码和 reason;如果是代理超时、网络切换、进程崩溃或 TCP/TLS 连接被直接切断,浏览器通常只会落到 1006。
- 1006 是异常关闭的本地表示,不能由服务端放进 Close 帧发送。
- 先记录
code、reason、wasClean和时间,再去对齐三层日志。 - 修复方向取决于断点:应用关闭、网关超时和传输中断的处理方式不同。
看到 1006 时,先把它理解为“没有完成 WebSocket 关闭握手”,而不是“服务端返回了一个叫 1006 的业务错误”。
WebSocket 1006 为什么没有服务端原因
RFC 6455 将 1006 定义为 Abnormal Closure,并明确它是保留值,不能作为 Close 控制帧里的状态码。浏览器的 CloseEvent.code 在没有收到 Close 帧时使用这个值,CloseEvent.reason 因而没有服务端提供的文本,wasClean 通常也会是 false。
这解释了一个常见误会:服务端日志里写了“准备关闭”,不等于客户端收到了 Close 帧。进程可能在写帧前崩溃,代理可能在转发前超时,或者移动网络切换让底层连接先断掉。此时浏览器只能报告结果,不能替你判断断点。

先把 CloseEvent 的四个字段记完整
不要只打印 event.code。将四个字段和连接建立时间、最后一条消息时间一起记录,才能判断是刚握手就断,还是空闲一段时间后被切断。
socket.addEventListener('close', (event) => {
// 记录客户端能观察到的全部关闭信息,方便和服务端日志按时间对齐。
console.warn('WebSocket closed', {
code: event.code,
reason: event.reason || '(empty)',
wasClean: event.wasClean,
closedAt: new Date().toISOString(),
});
});
判断可以先按这个表分层:
| 现象 | 更可能说明什么 | 先查哪里 |
|---|---|---|
1000 且 wasClean=true | 完成了关闭握手 | 业务关闭原因和用户操作 |
1006、reason 为空 | 未收到 Close 帧 | 代理超时、进程退出、网络链路 |
1008 或 1009 | 对端发送了明确的协议/策略结果 | 服务端策略和消息大小限制 |
按客户端、代理、服务端三层查断点
第一层看浏览器:确认连接 URL、握手是否成功、最后一次收发消息的时间,以及页面是否发生切换或网络类型变化。第二层看网关:检查 WebSocket Upgrade 是否被保持、空闲超时是否短于业务心跳间隔、是否有 upstream reset 或连接被回收。第三层看应用:确认是否进入了主动关闭分支、是否在写 Close 帧前异常退出、是否因部署或健康检查被终止。
最有价值的不是一句“连接断了”,而是同一个连接标识在三层日志中的最后状态。例如应用有“发送 1000”的记录而网关没有对应出站帧,优先查代理;应用完全没有关闭记录但进程刚重启,优先查进程生命周期;三层都没有错误而客户端恰好切换网络,则要保留传输中断的可能。

修复后用重连和心跳验证结果
重连可以恢复体验,但不能掩盖原因。客户端应使用递增退避和上限,避免服务端或代理异常时瞬间建立大量新连接;重连前保存必要的订阅状态,重连成功后再补订阅。心跳间隔要小于代理的空闲超时,并在服务端确认收到心跳后更新连接活跃时间。
function reconnectWithBackoff(connect, attempt) {
// 退避上限避免 1006 连续出现时形成重连风暴。
const delay = Math.min(30000, 1000 * 2 ** Math.min(attempt, 5));
return window.setTimeout(connect, delay);
}
如果用户主动退出页面,先调用 close(1000, 'user-left'),并在页面卸载后停止重连;如果是 1006,则把它当作需要重新建立连接的传输异常,同时保留一次可检索的客户端诊断记录。这样既能恢复连接,也不会把所有断开都伪装成正常关闭。
常见问题
1006 能不能由服务端直接发送?
不能。1006 是保留值,服务端不应把它写进 Close 帧;服务端应根据实际协议或业务情况发送允许的关闭码,异常断开则由客户端观察到 1006。
reason 为空是不是服务端没有写日志?
不一定。reason 只来自收到的 Close 帧,没有 Close 帧时为空很正常。服务端日志要和网关、客户端的时间及连接标识一起看。
遇到 1006 只要不断重连就行吗?
不行。先限制退避,再确认是否为代理空闲超时、应用重启、网络切换或协议错误;否则重连可能把故障放大成连接风暴。
Go GOOS GOARCH 如何确认目标架构实际生成的二进制
- 上一篇
- Go GOOS GOARCH 如何确认目标架构实际生成的二进制
- 下一篇
- Go archive/zip Writer.Close 失败时为什么不能忽略错误
-
- 文章 · 前端 | 4小时前 | 异步编程 · IndexedDB · 前端存储 · 事务 await IndexedDB TransactionInactiveError
- IndexedDB 事务为何不能跨 await
- 221浏览 收藏
-
- 文章 · 前端 | 5小时前 |
- BroadcastChannel 标签页关闭后为何收不到消息
- 199浏览 收藏
-
- 文章 · 前端 | 22小时前 | javascript · IntersectionObserver · 无限滚动 · 滚动加载 IntersectionObserver 前端性能
- IntersectionObserver 观察列表底部为何重复触发
- 106浏览 收藏
-
- 文章 · 前端 | 23小时前 | 前端 · url · javascript · URLSearchParams append getAll
- URLSearchParams 生成重复参数怎么保留多个值
- 483浏览 收藏
-
- 文章 · 前端 | 1天前 | 前端开发 · 网络请求 · Fetch API · 异步取消 · ReadableStream · Fetch AbortController ReadableStream Response.Body AbortError
- AbortController 取消 fetch 后如何清理未消费的 response body
- 492浏览 收藏
-
- 文章 · 前端 | 1天前 | Response · javascript · Fetch API · 异步请求 · 前端排错 · Fetch ReadableStream Response.json bodyUsed 前端请求
- Fetch 读取 response.json 后为何不能再次读取 body
- 323浏览 收藏
-
- 文章 · 前端 | 1天前 | 前端 · Service Worker · 浏览器API · 离线缓存 · 脚本更新 · Service Worker waiting registration.update updatefound installing active
- Service Worker registration.update 怎么判断新脚本已经下载
- 394浏览 收藏
-
- 文章 · 前端 | 1天前 | javascript · 性能排查 · ResizeObserver · ResizeObserver 尺寸监听 前端布局
- ResizeObserver 回调中修改尺寸为什么会循环触发
- 481浏览 收藏
-
- 文章 · 前端 | 1天前 | javascript · 前端性能 · IntersectionObserver · 懒加载 · rootMargin · 图片懒加载 IntersectionObserver 前端性能 rootMargin
- IntersectionObserver rootMargin 怎么提前触发图片加载
- 263浏览 收藏
-
- 文章 · 前端 | 1天前 |
- structuredClone 转移 ArrayBuffer 后为什么原缓冲区失效
- 178浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 82次使用
-
- OpenCompass
- OpenCompass是上海AI实验室推出的开源大模型评测平台,提供CompassKit、CompassHub和CompassRank三大核心组件,支持LLM及多模态模型的一站式标准化评估与排行榜查询。
- 7次使用
-
- SuperCLUE
- SuperCLUE是权威的中文大语言模型综合评测基准,涵盖语言理解、知识应用、AI Agent智能体及安全性等12项核心能力。通过多轮对话与客观测试,定期发布榜单与技术报告,为模型研发、优化及行业选型提供科学依据。
- 242次使用
-
- C-Eval
- 深入了解C-Eval中文评估套件,涵盖52个学科与4级难度。本文详解其功能特点、Zero-shot/Few-shot使用方法及代码示例,助您全面评测LLM中文理解与泛化能力。
- 166次使用
-
- AI Prompt Library
- 探索AI Prompt Library免费资源库,涵盖营销、写作及多场景AI提示词。兼容ChatGPT、Claude等工具,一键复制优化输出,提升工作效率。
- 100次使用
-
- JavaScript函数定义及示例详解
- 2025-05-11 502浏览
-
- 智能体安全引领产业升级——国内AI安全产品市场深度分析
- 2026-08-21 501浏览
-
- CSS变量简化按钮悬停效果技巧
- 2026-05-31 501浏览
-
- JavaScript符号类型详解与应用
- 2026-05-31 501浏览
-
- HTML剪贴板复制粘贴怎么用
- 2026-05-26 501浏览

