直接用 go get github.com/olahol/melody 安装即可,无需手动处理 gorilla/websocket;必须注册 handlerequest 及至少一个事件处理器(如 handleconnect),否则返回 400;公网部署需调小 pongwait 和 pingperiod 并同步调整 nginx 超时配置;广播性能瓶颈在于 session map 锁竞争,建议用 broadcastatomic 和分组管理优化。

直接用 go get 安装 Melody 即可,无需手动处理 gorilla/websocket
Melody 本身不单独发布二进制或 CLI 工具,它是一个 Go 模块,安装就是引入依赖。执行:go get github.com/olahol/melody
即可完成安装。gorilla/websocket 是它的底层依赖,go mod 会自动拉取并锁定版本(当前主流是 v1.5.x),不需要你额外 go get 或指定兼容性。
常见错误现象:
• 报错 cannot find package "github.com/gorilla/websocket":说明本地 GOPROXY 配置异常或网络受限,不是 Melody 缺少依赖;
• go.mod 中出现重复的 github.com/gorilla/websocket 版本:通常因其他库也引用了该包,可用 go mod graph | grep gorilla 查冲突源,再 go mod edit -replace 统一版本。
Melody.New() 后必须注册 HandleRequest,否则连接直接 400
Gin 或 net/http 路由中,仅调用 m.HandleRequest(c.Writer, c.Request) 不够——它只是“接管”连接升级流程,但若没提前绑定 HandleConnect 或 HandleMessage,Melody 内部会拒绝握手,返回 HTTP 400 错误(无明确日志提示)。
- 必须至少注册一个事件处理器,哪怕空实现:
m.HandleConnect(func(*melody.Session) {}) - 如果只关心消息收发,
HandleMessage是最低要求;断开事件HandleDisconnect可选但强烈建议加上,用于资源清理 - Gin 场景下,确保路由是
r.GET("/ws", ...),不能用POST或Any,WebSocket 协议要求 GET 方法发起 handshake
默认配置在公网环境容易掉连,PongWait 和 PingPeriod 必须调小
Melody 默认的 PongWait: 60s、PingPeriod: 54s 在真实公网链路中极易触发超时断连——中间代理(如 Nginx、CDN、运营商 NAT)常主动 kill 空闲连接,实际存活时间往往低于 30s。
实操建议:
• 生产环境统一设为:PongWait: 30 * time.Second、PingPeriod: 25 * time.Second
• 若使用 Nginx,还需同步调整其 proxy_read_timeout 和 proxy_send_timeout ≥ 35s,否则 Nginx 先断连,Melody 还没来得及发 ping
Colly 是一个用于 Go 语言的快速开源爬取和爬虫框架。它适用于从简单的页面提取到异步爬虫处理大量页面集合,支持请求回调和结构化解析。
验证方法:用浏览器开发者工具观察 WebSocket 连接状态,若频繁出现 WebSocket is closed before the connection is established 或连接数陡降,大概率是心跳参数失配。
广播性能瓶颈不在 Broadcast,而在 session 数据结构和锁竞争
m.Broadcast() 看似简单,但底层遍历 hub.sessions map 并发写入每个 Session 的 writeCh 通道。当连接数超过 2000,RWMutex 读锁争用会明显拖慢广播吞吐。
优化关键点:
• 不要反复调用 m.Broadcast() 发送相同消息——改用 m.BroadcastAtomic()(需自行封装一次序列化)
• 避免在 HandleMessage 中直接广播原始 []byte,先做必要过滤(如剔除发送者自身)
• 若需定向推送(如房间、用户组),别用 for range hub.sessions 手动筛,改用 melody.Session.Set() + 自定义 map 管理分组,减少锁持有时间
容易被忽略的细节:Melody 的 Session 指针是唯一标识,但 hub.sessions map 的 key 就是该指针。一旦 session 断开,Melody 会从 map 删除它——所以遍历时无需加额外判空逻辑,但也不能缓存该 map 副本用于异步广播,否则可能 panic。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










