面对数万级并发 websocket 连接,避免使用带单 mutex 的 map 维护连接列表,转而采用基于发布/订阅的去中心化通信模型,并结合分布式消息中间件实现水平扩展。
在高并发实时通信场景中(如每 100ms 向 >50,000 个活跃客户端广播消息),传统“维护全局连接列表 + 单锁遍历发送”的方式存在严重瓶颈:
✅ 正确架构思路:解耦连接管理与消息分发
每个 WebSocket 连接不再被“集中注册”,而是作为独立消费者,通过唯一标识(如 user_id、session_id 或 room:general)向中心化消息枢纽(Hub)订阅(Subscribe) 相关主题。消息生产者(如业务 goroutine)仅需向对应主题 发布(Publish),由底层消息系统完成路由与投递。
// 示例:客户端连接时订阅自身主题(Go + Gorilla WebSocket + NSQ 客户端)
func handleWS(w http.ResponseWriter, r *http.Request) {
conn, _ := upgrader.Upgrade(w, r, nil)
defer conn.Close()
// 生成或提取连接标识(建议从 JWT / Cookie / URL 参数获取)
userID := extractUserID(r)
// 启动订阅协程:监听专属主题(如 "user:12345")和全局主题(如 "broadcast")
go subscribeToNSQ(userID, conn)
// 心跳与读取逻辑...
}? 关键技术选型建议:
方案,如 NSQ(轻量、最终一致性、支持 topic/channel 分层)、NATS(低延迟、支持 JetStream 持久化)或 Apache Pulsar(多租户、分层存储)。避免自研“带锁 map”或 Redis Pub/Sub(后者无连接状态感知、易丢消息)。 ⚠️ 注意事项:
总结:规模化的实时服务不是“管住所有连接”,而是“让连接自主发现所需消息”。放弃中心化连接列表,拥抱发布/订阅范式 + 分布式消息总线,是支撑 50K+ WebSocket 连接稳定、低延迟、可伸缩的工程共识。