Iris 不推荐也不内置长轮询,因其基于 net/http 的 goroutine 模型易导致泄漏、超时失控和连接堆积;真需支持应绕过 Iris 路由直连 http.ServeMux 手动管理上下文与超时。

Iris 框架本身不推荐、也不内置长轮询(Long Polling)实现——它专为高性能 HTTP 路由和 WebSocket 设计,而长轮询是种“退化方案”,只在 WebSocket 不可用且客户端极度受限时才考虑。直接在 Iris 里手写长轮询,容易踩 goroutine 泄漏、超时失控、连接堆积三类坑。
为什么 Iris 不该用来做长轮询
长轮询本质是让 HTTP 请求挂起,等有数据或超时才返回。但 Iris 的默认 HTTP 处理模型基于标准 net/http,每个请求独占一个 goroutine;若你用 time.Sleep 或阻塞 channel 等待消息,这个 goroutine 就一直卡着,无法释放。1000 个并发长轮询 = 至少 1000 个常驻 goroutine,内存和调度压力会快速飙升。
- 没有自动连接清理机制:客户端断连后,Iris 不会主动通知你 goroutine 已失效
- 超时必须手动设且严格匹配:
context.WithTimeout得套在 handler 最外层,漏一层就可能永久挂起 - 没法复用连接:HTTP/1.1 长轮询每次响应完就得重建连接,而 Iris 的中间件和日志默认按“请求-响应”生命周期设计,状态难延续
真要支持长轮询,得绕开 Iris 的路由直连 http.ServeMux
如果你的场景确实无法用 WebSocket(比如某些企业内网防火墙只放行 80/443 且禁掉 WebSocket 升级头),那应该绕过 Iris 的 app.Get,改用底层 http.ServeMux 注册裸 handler,并自己管理上下文取消和超时:
func longPollHandler(w http.ResponseWriter, r *http.Request) {
// 必须显式设置超时,不能依赖全局 server.ReadTimeout
ctx, cancel := context.WithTimeout(r.Context(), 30*time.Second)
defer cancel()
<pre class="brush:php;toolbar:false;">// 用 channel 等待事件(比如从 Redis pubsub 或本地 map 广播)
select {
case msg := <-waitChan:
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]string{"msg": msg})
case <-ctx.Done():
if errors.Is(ctx.Err(), context.DeadlineExceeded) {
w.WriteHeader(204) // No Content,表示无新数据
}
}}
立即学习“go语言免费学习笔记(深入)”;
// 手动注册到 mux,不走 Iris 路由链 http.DefaultServeMux.HandleFunc("/lp", longPollHandler)
- 别用
app.Get("/lp", ...):Iris 中间件(如日志、JWT)会干扰长连接生命周期 - 别用
iris.Context:它内部封装了 responseWriter,不支持多次 WriteHeader 或流式写入 - channel 必须带缓冲或用
select防阻塞,否则 goroutine 会被永远卡住
长轮询的替代路径比硬写更可靠
与其在 Iris 里拧巴地实现长轮询,不如换更轻量、更可控的方案:
- 用
go-socket.io+ 自动降级:它内置 fallback 到长轮询的能力,且所有状态(连接、房间、超时)都封装好了,server.SetHeartbeat(&socketio.Heartbeat{Interval: 25 * time.Second})可控 - 前端降级用
EventSource(SSE):Iris 支持流式响应,w.Header().Set("Content-Type", "text/event-stream")+w.(http.Flusher).Flush()更简单、更省资源 - 反向代理层兜底:Nginx 配置
proxy_buffering off+proxy_cache off,把长轮询请求透传给一个极简 Go HTTP server(不用 Iris),专注做一件事
真正难的不是怎么“写出来”,而是怎么让成百上千个长连接不把服务拖垮。Iris 的优势在路由性能和 WebSocket 集成,强行让它扛长轮询,就像拿赛车引擎去拖货船——能转,但效率低、风险高、维护累。


















