Iris 框架原生不提供 WebSocket 实现,仅通过 websocket 子包轻量封装第三方库(如 gorilla/websocket),需手动启用 Hijack、正确注册 handler、严格匹配 Path 路径,并自行实现心跳、重连与连接管理。

Iris 框架原生不提供 WebSocket 实现,它只提供 websocket 子包作为轻量封装,底层仍依赖第三方库(如 gorilla/websocket)——这是最容易被误读的第一点。
为什么 iris.New() 后直接用 websocket.New() 会报错或连接失败
常见错误现象:panic: websocket: response does not implement http.Hijacker 或前端 WebSocket connection to 'ws://...' failed。这是因为 Iris 的 HTTP server 默认不启用连接劫持(hijacking),而 WebSocket 协议必须通过 http.Hijacker 接管底层 TCP 连接。
解决办法只有两个:
- 确保使用
iris.WithoutVersionChecker和iris.WithoutServerError(iris.ErrServerClosed)等安全配置之外,必须显式启用 Hijack 支持:在app.Listen()中传入iris.WithoutBodyConsumptionOnUnmarshal不起作用,真正有效的是—— - 改用
app.Run(iris.Addr(":8080"), iris.WithoutInterruptHandler, iris.WithStdLogger)并确认你的 Iris 版本 ≥ v12.2.0(旧版websocket.Config中的Endpoint字段在 v12.1.x 之后已弃用,应改用Path)
iris/v12/websocket 包的正确初始化方式
关键不是“挂载”,而是“注册 handler 到标准 HTTP 路由”。websocket.New() 返回的是一个 http.Handler,需手动绑定到 app.Any() 或 app.Get(),不能靠 Adapt() 自动注入(该方法在 v12+ 已标记为 deprecated)。
实操建议:
- 不要用
app.Adapt(ws),改写为:app.Get("/ws", ws.Handler())或app.Any("/ws", ws.Handler())(推荐Any,因 WebSocket 升级请求是GET,但部分代理/CDN 可能重写 method) -
websocket.Config中的Path必须与路由路径严格一致,例如Path: "/ws"→ 路由必须是app.Any("/ws", ...),否则握手 404 - 避免在
OnConnection回调里做阻塞操作(如同步 DB 查询),否则会卡住整个 WebSocket goroutine;用go func() { ... }()启新协程处理消息收发
广播消息时遍历连接容易漏掉新进连接
典型问题:客户端 A 连接后收到推送,B 连接后再推送,A 收不到,只有 B 收到。这是因为 ws.GetConnectionsByRoom("/room") 返回的是调用时刻的快照,不是实时引用。
根本原因在于 Iris 的 websocket.Connection 是单次生命周期对象,不支持自动房间同步。解决方案只有两种:
- 改用全局 map +
sync.RWMutex手动管理活跃连接(简单可靠,适合中小规模) - 放弃
iris/websocket,直接集成github.com/gorilla/websocket或github.com/googollee/go-socket.io(后者支持命名空间、房间、自动重连,更适合生产环境) - 若坚持用 Iris 封装,务必在
OnDisconnect中主动从 map 删除连接,并在OnConnection中立即加入——Join()方法本身不保证原子性,不能替代手动注册
最常被忽略的一点:Iris 的 websocket 包没有内置心跳保活和断线重连逻辑,所有超时、重连、消息确认都得自己实现。别指望 EmitMessage() 调用成功就等于客户端收到了——它只表示写入 socket 缓冲区成功,网络抖动或客户端崩溃时完全无感知。


















