WebSocket路由必须用iris.WebSocket单独注册,不可在普通GET路由中调用ws.Upgrade;需显式设置读写超时、使用server.Broadcast广播、通过websocket.GetContext获取Iris上下文,并确保反向代理透传Upgrade头。

WebSocket路由必须用 iris.WebSocket 单独注册,不能塞进 app.Get
直接在普通HTTP路由里调用 ws.Upgrade 或手动写 101 Switching Protocols 会失败。浏览器发起 ws:// 连接时,返回 404 或 500,控制台显示 net::ERR_CONNECTION_REFUSED 或 Error during WebSocket handshake。
正确做法是:先初始化一个 neffos.Server 实例,再用 app.WebSocket("/ws", server) 挂载——这个路径就是前端 new WebSocket("ws://localhost:8080/ws") 要连的地址。
-
iris.WebSocket内部自动处理Upgrade头、协议协商和连接生命周期,别自己伪造 - 不能把 WebSocket 路由和普通 HTTP 路由混在同一个
Handle或中间件链里,Iris 会跳过 WebSocket 中间件 - 如果用了 Nginx 或其他反向代理,必须透传
Upgrade和Connection头,否则握手直接失败
读写超时必须显式设置,且每次操作前重置
不设超时会导致 goroutine 堆积、内存泄漏。典型现象是客户端断网后,服务端卡在 conn.ReadMessage() 阻塞,连接状态仍显示“在线”,但消息收不到。
每个连接在 OnConnect 回调里就要设初始超时,并在每次 ReadMessage 和 WriteMessage 前重置:
conn.SetReadDeadline(time.Now().Add(10 * time.Second))
_, msg, err := conn.ReadMessage()
if err != nil {
return // 断开连接
}
conn.SetWriteDeadline(time.Now().Add(5 * time.Second))
conn.WriteMessage(websocket.TextMessage, msg)
- 读超时建议 5–15 秒;写超时略短(3–5 秒),避免缓冲区积压
- 不要在
OnMessage里写defer conn.Close()—— 关闭应由业务逻辑触发(如心跳超时、用户主动下线) -
websocket.Conn不是线程安全的,禁止同一连接并发调用WriteMessage
广播消息必须用 server.Broadcast,别遍历 GetConnections()
手动遍历所有连接再逐个 WriteMessage 极易出错:连接可能已关闭、写缓冲满、或超时未清理,常见 panic 是 write tcp: use of closed network connection。
server.Broadcast 内部做了三件事:检查连接状态、加写锁保护、跳过错误连接。适合群聊、通知等场景。
- 它只发给当前命名空间(namespace)下的活跃连接
- 如果需要定向推送,优先用
ns.Conn.Emit或按用户 ID 维护映射表,而不是暴力遍历 - 注意
neffos.Namespaces的定义方式,"default"是默认命名空间,别漏写
从 WebSocket 连接里取 Iris Context 得用 websocket.GetContext
neffos.Conn 本身不带 Iris 的上下文信息,但很多中间件逻辑(比如 session、日志、i18n)依赖 iris.Context。直接 cast 或强转会 panic。
必须通过 Iris 提供的辅助函数提取:
onChat := func(ns *neffos.NSConn, msg neffos.Message) error {
ctx := websocket.GetContext(ns.Conn) // ✅ 正确
// ctx.ResponseWriter()、ctx.Values()、ctx.Session() 全都能用
return nil
}
- 这个
ctx是只读快照,不能调用ctx.Next()或修改响应头 - 如果要在 WebSocket 里读 session,确保 session middleware 已全局注册(
app.Use(session.Handler())) - 别在
OnConnect里存ctx到结构体字段——它生命周期短,且不可复用
实际部署时最容易被忽略的是反向代理配置和超时联动。Nginx 的 proxy_read_timeout 必须大于服务端读超时,否则它会在握手完成前主动断连;Kubernetes Ingress 同理,得显式开启 WebSocket 支持并透传头字段。


















