Beego本身不内置WebSocket实现,必须依赖github.com/gorilla/websocket手动接管连接升级;需在beego.Controller.Get()中调用upgrader.Upgrade()完成协议升级,此后Beego上下文失效,仅能通过*websocket.Conn读写,且WriteMessage()非线程安全,须配专属channel与writePump goroutine。

Beego 本身不内置 WebSocket 实现,必须依赖 github.com/gorilla/websocket 手动接管连接升级——这是所有 Beego WebSocket 应用的起点,绕不开。
beego.Controller.Get() 中调用 upgrader.Upgrade() 是唯一可行路径
Beego 的 HTTP 路由机制不支持直接注册 WebSocket handler,只能在控制器的 Get() 方法里手动处理协议升级。任何试图用 beego.Router("/ws", ...) 绑定非 HTTP handler 的做法都会失败。
-
upgrader.Upgrade()必须传入this.Ctx.ResponseWriter和this.Ctx.Request,不能用原始http.ResponseWriter或自行构造请求 - 升级成功后,Beego 的上下文生命周期即终止,
this.Data、this.Render()等 MVC 功能全部失效,后续只能靠*websocket.Conn读写 - 务必在
Upgrade()后立即检查err,失败时直接 return,不要继续执行后续逻辑(比如误调this.Redirect())
upgrader.CheckOrigin 默认拒绝跨域,前端连不上就是它在拦
开发阶段浏览器访问 http://localhost:8080 连 ws://localhost:8080/ws 通常没问题,但一旦部署到不同域名或端口(如 Nginx 反代后),upgrader 默认会因 Origin 不匹配而返回 403。
- 最简方案:设置
upgrader.CheckOrigin = func(r *http.Request) bool { return true }(仅限开发/内网) - 生产环境应白名单校验:
return r.Header.Get("Origin") == "https://your-domain.com" - 别漏掉
import "net/http",否则编译报错
Nginx 反向代理 WebSocket 必须透传 Upgrade 和 Connection 头
没配对这两个 header,WebSocket 连接会在握手阶段卡住,浏览器控制台显示 failed: Error during WebSocket handshake: Unexpected response code: 200。
- 在
http块中定义:map $http_upgrade $connection_upgrade { default upgrade; '' close; } - 在
location /ws块中添加:proxy_set_header Upgrade $http_upgrade;和proxy_set_header Connection $connection_upgrade; - 必须加
proxy_read_timeout 86400;,否则空闲 60 秒后连接被 Nginx 断开(默认值)
gorilla/websocket 的 WriteMessage() 不是线程安全的
多个 goroutine 并发调用同一个 *websocket.Conn 的 WriteMessage() 会导致 panic:“concurrent write to websocket connection”。
- 典型场景:广播消息时遍历
clientsmap,每个 client 单独起 goroutine 写;结果多个 goroutine 同时写同一连接 - 正确做法:为每个连接维护一个专属的
messages chan []byte,另起一个writePump()goroutine 从该 channel 读并调用WriteMessage() - 关闭连接前务必先
close(messages),再conn.Close(),否则writePump会阻塞在 channel 读取上
Beego 的路由和上下文模型与 WebSocket 的长连接本质存在天然张力,所有“自动集成”都是幻觉。真正稳的方案,永远是把 Beego 当 HTTP 路由器用,把 gorilla/websocket 当底层连接引擎用,中间那层胶水代码——尤其是并发控制和连接生命周期管理——得亲手写清楚,少一行都可能在线上静默崩溃。


















