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 反代需转发 UpgradeConnection: upgrade 头,应用侧见部署章节。

常见追问

  • 追问:为什么框架不内置 WebSocket 了?——第三方生态(gorilla 等)成熟,内置封装收益低、维护成本高;官方倾向“轻内核 + 推荐组件”,旧封装保留但标记弃用以兼容存量代码。
  • 追问:给所有在线用户广播怎么做?——框架没有内置房间/广播能力,需自建连接表 + 分发 goroutine,或引入消息队列/独立网关。

记忆点

  • 现行姿势:ghttp 路由 + gorilla Upgrade + 收发循环;旧 ghttp.WebSocket/r.WebSocket() 已弃用勿用。
  • 鉴权、心跳、广播三件事框架都不管;弃用标注与示例细节以官方文档为准。
笔记加载中…