WebSocket:ghttp 支持现状与推荐方案
面试问法:GoFrame 里 WebSocket 怎么做?框架内置吗?官方是不是弃用了? 一句话结论:v2 的 ghttp 不再把 WebSocket 作为内建一等能力维护——历史上提供的
ghttp.WebSocket封装对象在官方源码中已标记 Deprecated(以官方源码标注为准);官方现行推荐是“普通路由 + gorilla/websocket 升级连接”,官方文档保留“WebSocket 服务”章节与示例,现状以官方文档为准。
支持现状(如实说明)
- 曾有:框架内提供
ghttp.WebSocket/r.WebSocket()封装对象,官方源码已标记弃用,新代码不应再使用。 - 现在:WebSocket = 普通路由注册 + 一次协议升级 + 收发循环,升级动作交给第三方
gorilla/websocket。 - 官方文档提供服务端、Go 客户端与 H5 聊天演示的完整示例。
- 框架不做同源/鉴权检查:来源校验、Token 校验、连接管理(房间/广播/心跳)全部由业务自理。
Echo 服务端最短代码
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool { return true }, // 生产必须按业务校验
}
s := g.Server()
s.BindHandler("/ws", func(r *ghttp.Request) {
ws, err := upgrader.Upgrade(r.Response.Writer, r.Request, nil)
if err != nil {
r.Response.WriteStatus(400) // 升级失败要写回响应
return
}
defer ws.Close()
for {
mt, msg, err := ws.ReadMessage()
if err != nil { break } // 连接关闭或出错
if err = ws.WriteMessage(mt, msg); err != nil { break }
}
})
s.SetPort(8000)
s.Run()
Go 客户端用 websocket.DefaultDialer.Dial 连接;浏览器端 new WebSocket("ws://host/ws"),监听 onopen/onmessage/onclose/onerror。
工程化要点
- 升级前鉴权:Origin 白名单 + Token(请求头/query/首帧消息)校验,失败即拒。
- 连接管理自建:登记在线连接(map/会话表),同一连接避免并发写,可串行化收发。
- 心跳保活:定期 Ping / 读超时剔除死链,防止经过的代理与负载均衡回收空闲连接。
- 加密通道 wss:给 Server 开启 HTTPS(
s.EnableHTTPS(cert,key))即可,升级逻辑不变。 - 部署:nginx 反代需转发
Upgrade与Connection: upgrade头,应用侧见部署章节。
常见追问
- 追问:为什么框架不内置 WebSocket 了?——第三方生态(gorilla 等)成熟,内置封装收益低、维护成本高;官方倾向“轻内核 + 推荐组件”,旧封装保留但标记弃用以兼容存量代码。
- 追问:给所有在线用户广播怎么做?——框架没有内置房间/广播能力,需自建连接表 + 分发 goroutine,或引入消息队列/独立网关。
记忆点
- 现行姿势:ghttp 路由 + gorilla Upgrade + 收发循环;旧
ghttp.WebSocket/r.WebSocket()已弃用勿用。 - 鉴权、心跳、广播三件事框架都不管;弃用标注与示例细节以官方文档为准。