0

0

如何在Golang中实现Websocket的心跳机制 Go语言Ping/Pong消息保活

P粉602998670

P粉602998670

发布时间:2026-03-17 16:07:21

|

266人浏览过

|

来源于php中文网

原创

服务端需手动注册SetPongHandler并配合SetReadDeadline实现可靠心跳;用time.Ticker每25秒发Ping,WriteControl需设写超时;客户端应额外发JSON心跳包并与服务端ACK交互;Nginx等中间件proxy_read_timeout须大于服务端最大空闲窗口。

如何在golang中实现websocket的心跳机制 go语言ping/pong消息保活

服务端怎么发 Ping 并正确响应 Pong

gorilla/websocket 不会自动回 Pong,必须手动注册 SetPongHandler,否则客户端发来的 Ping 会被丢弃,导致连接被误判为失效。同时,仅靠响应 Pong 还不够——你得用 SetReadDeadline 把“最后收到消息时间”和“超时窗口”绑死,不然心跳就形同虚设。

  • 每次收到 Pong 后立刻调用 conn.SetReadDeadline(time.Now().Add(60 * time.Second)),重置读超时
  • time.Ticker25 * time.Second 主动发一次 WriteControl(websocket.PingMessage, nil, ...),别用 WriteMessage ——后者不支持控制帧
  • 务必在 WriteControl 中传入合理的 deadline(比如 time.Now().Add(5 * time.Second)),否则写失败时 goroutine 会卡住
  • 不要在 SetPongHandler 里做耗时操作,它运行在读协程中,阻塞会导致整个连接 hang 住

客户端要不要自己发心跳包

浏览器原生 WebSocket 会自动响应服务端 Ping,但只靠这个不够:它无法探测服务端是否真在线,也缺乏可观测性。所以建议客户端额外发 JSON 心跳包,比如 {"type":"heartbeat"},和服务端心跳解耦,便于日志追踪和协议扩展。

  • setInterval30 * time.Second 调用 ws.send(JSON.stringify({type:'heartbeat'}))
  • 服务端收到后应返回 ACK(如 {"type":"heartbeat_ack"}),而不是只回 Pong;这样客户端才能区分“网络通但服务挂了”和“纯网络断开”
  • 客户端需维护 lastReceivedAt 时间戳,若 60 秒内既没收到业务消息、也没收到 ACK 或 Pong,就触发重连
  • 别把心跳逻辑塞进 onmessage 回调里做判断——它可能被大量业务消息淹没,应独立计时

为什么 Nginx 一上就掉连接

不是代码问题,是中间件默认超时比你的心跳还短。Nginx 的 proxy_read_timeout 默认 60 秒,而你的服务端 Ping 间隔设成 30 秒、超时设成 45 秒,看似合理,但实际经过 Nginx 后,它会在第 61 秒直接切断连接,且不通知上下游。

  • 必须把 Nginx 配置里的 proxy_read_timeout 改成至少 75s(大于服务端最大空闲窗口)
  • 加上 proxy_set_header Connection '',防止 Nginx 复用连接干扰 WebSocket 升级头
  • 如果用了负载均衡器(如 AWS ALB),同样要检查其空闲超时设置,常见值是 60~3500 秒不等,不能假设它“默认兼容”
  • 上线前务必用 tcpdump 抓包验证:确认 Ping 帧真正到达客户端,且 Pong/ACK 确实返回到了服务端

WriteMessage 并发写崩溃怎么办

gorilla/websocket 的 WriteMessageWriteControl 都不是并发安全的。一旦心跳协程、业务写协程、错误关闭协程三者同时调用写方法,大概率触发 panic: write tcp ... use of closed network connection 或更隐蔽的 data race。

Waifulabs
Waifulabs

一键生成动漫二次元头像和插图

下载

立即学习go语言免费学习笔记(深入)”;

  • 最稳方案是只留一个写协程,所有写请求走 chan []bytechan Message 通道
  • 心跳协程不直接调用 WriteControl,而是发信号到写通道,由统一写协程处理
  • 如果坚持多点写,必须对 *websocket.Conn 加互斥锁(sync.Mutex),但要注意锁粒度——别把 WriteControlClose 包进同一把锁,否则关连接时会死锁
  • 永远在写之前检查 conn.IsClosed()(需自行封装或用 conn.WriteMessage 返回的 error 判断),别依赖 defer 或外部状态标记

心跳机制本身不难写,难的是它暴露的是整个链路的脆弱性:Nginx 配置、负载均衡策略、客户端休眠行为、甚至 TLS 握手重试都会干扰它。别只盯着 Go 代码,上线前一定要在真实部署拓扑里跑满 2 小时压力测试,看连接是否真能扛过三次心跳周期。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
golang如何定义变量
golang如何定义变量

golang定义变量的方法:1、声明变量并赋予初始值“var age int =值”;2、声明变量但不赋初始值“var age int”;3、使用短变量声明“age :=值”等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

211

2024.02.23

golang有哪些数据转换方法
golang有哪些数据转换方法

golang数据转换方法:1、类型转换操作符;2、类型断言;3、字符串和数字之间的转换;4、JSON序列化和反序列化;5、使用标准库进行数据转换;6、使用第三方库进行数据转换;7、自定义数据转换函数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

247

2024.02.23

golang常用库有哪些
golang常用库有哪些

golang常用库有:1、标准库;2、字符串处理库;3、网络库;4、加密库;5、压缩库;6、xml和json解析库;7、日期和时间库;8、数据库操作库;9、文件操作库;10、图像处理库。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

357

2024.02.23

golang和python的区别是什么
golang和python的区别是什么

golang和python的区别是:1、golang是一种编译型语言,而python是一种解释型语言;2、golang天生支持并发编程,而python对并发与并行的支持相对较弱等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

214

2024.03.05

golang是免费的吗
golang是免费的吗

golang是免费的。golang是google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的开源编程语言,采用bsd开源协议。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

410

2024.05.21

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

510

2025.06.09

golang相关判断方法
golang相关判断方法

本专题整合了golang相关判断方法,想了解更详细的相关内容,请阅读下面的文章。

201

2025.06.10

golang数组使用方法
golang数组使用方法

本专题整合了golang数组用法,想了解更多的相关内容,请阅读专题下面的文章。

1559

2025.06.17

抖漫入口地址合集
抖漫入口地址合集

本专题整合了抖漫入口地址相关合集,阅读专题下面的文章了解更多详细地址。

1

2026.03.17

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Go 教程
Go 教程

共32课时 | 6.3万人学习

Go语言实战之 GraphQL
Go语言实战之 GraphQL

共10课时 | 0.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号