根本原因是nginx默认proxy_read_timeout=60秒静默断连,需同步配置proxy_read_timeout 86400、proxy_send_timeout 86400、proxy_http_version 1.1、proxy_set_header upgrade $http_upgrade、proxy_set_header connection "upgrade",并关闭proxy_buffering和proxy_cache,配合go服务端显式设置读写deadline及手动处理ping/pong心跳。

WebSocket 连接频繁断开怎么 fix
根本不是协议问题,而是中间件(Nginx、Cloudflare)或 Go 自身超时机制把空闲连接掐了。不设 Deadline 就等于裸奔。
-
conn.SetReadDeadline(time.Now().Add(30 * time.Second))和conn.SetWriteDeadline必须在每次读/写前显式调用,不能只设一次 - gorilla/websocket 不自动响应 Ping,得手动注册:
conn.SetPingHandler(func(appData string) error { return conn.WriteMessage(websocket.PongMessage, nil) }) - Nginx 配置里漏掉
proxy_read_timeout 60和proxy_send_timeout 60,默认 60 秒静默就断,客户端收不到 Close 帧,直接close 1006
广播性能卡在 1000 连接以下怎么办
用 map[*websocket.Conn]bool + 全局 sync.RWMutex 遍历写,500 连接就开始 CPU 暴涨,瓶颈不在网卡,而在锁和阻塞写。
- 每个连接绑定独立的
chan []byte,启动 goroutine 从 chan 消费并conn.WriteMessage,避免广播时碰连接对象本身 - 广播逻辑只往多个 chan 发送字节切片,完全无锁;注意加
select { case ch 防止单个慢连接拖垮整个 goroutine - 别用
conn.WriteMessage直接塞大消息,超过 MTU 容易触发 TCP 分片重传;建议拆成 ≤ 8KB 的帧
离线消息存 Redis 为什么拉取慢还乱序
LPUSH user:123 msg 看似简单,但 LRANGE 拉历史时会全量扫描,且多客户端并发写入导致顺序错乱。
Go语言(Golang)1.26.0版本提供 Go 官方 Windows amd64 MSI 安装包下载入口,版本号 1.26.0,可用于旧项目维护、兼容性测试和指定版本开发环境配置。
- 改用 Stream 类型:
XADD user:123 * msg,天然有序、支持消费者组、可按 ID 范围精确拉取 - 避免用用户 ID 当 key 存海量消息,按时间分片,比如
user:123:202607(年月),防止单 key 过大 - 客户端拉取后必须
XDEL或XTRIM控制长度,否则内存持续涨;别依赖 TTL,Stream 不支持 key 级过期
点对点消息如何不丢、不重复、不乱序
TCP 只保证传输不丢包,不保证应用层消息原子性。两个客户端各自发、各自收,中间没协调者,很容易出现“已读未达”或重复投递。
- 服务端为每条点对点消息生成唯一
msg_id(如uuid.NewString()),存入 Redis 的pending:from:tohash 中,带 TTL - 接收方成功处理后,主动上报
ACK msg_id,服务端删 pending;超时未 ACK 则重推(最多 3 次) - 发送方本地缓存最近 100 条
msg_id,收到重复 ACK 或服务端返回 “already delivered” 时直接丢弃
真实压测中,最容易被忽略的是连接生命周期管理:不是所有断连都要立刻踢人,得结合心跳间隔、重连窗口、客户端版本做分级清理;否则网络抖动时在线数跳变,状态同步直接雪崩。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










