Golang使用SSE长连接被超时关闭,如何仅为SSE接口单独配置超时规则
问题根源
10秒断开的问题和Heroku无关,是Go标准库http.Server的超时配置逻辑导致的:
http.Server.WriteTimeout定义的是从请求接收开始到响应完全写完的总时长上限,和中间是否有数据传输无关。哪怕每秒都在发送ping消息,只要总连接时长到了10秒,连接就会被强制断开。ReadTimeout是读取整个请求(包括请求体)的最长时间,对于SSE这类长连接,请求头早就读取完成,但全局配置的ReadTimeout仍会限制总连接时长,这也是你移除该配置后本地运行恢复正常的原因。
分路由配置超时的实现方案
想要保留普通接口的超时安全配置,同时给SSE接口开特例,推荐用http.TimeoutHandler中间件实现路由级的超时控制,不要用全局的ReadTimeout/WriteTimeout配置:
具体实现步骤
- 全局
http.Server仅保留安全必要的ReadHeaderTimeout配置(用于防范慢请求攻击,不会影响长连接逻辑),移除全局的ReadTimeout和WriteTimeout:
httpServer := &http.Server{ // 仅限制读取请求头的最长时间,不影响后续长连接 ReadHeaderTimeout: 5 * time.Second, }
- 所有非SSE的普通接口用
http.TimeoutHandler包裹,设置你需要的10秒超时:
// 示例:给普通业务接口加10秒超时 http.Handle("/api/your-common-api", http.TimeoutHandler(yourCommonHandler, 10*time.Second, "request timeout"))
- SSE接口无需使用超时中间件,直接注册handler即可不受全局超时限制:
// SSE接口单独注册,无超时限制 http.Handle("/api/sse", sseHandler)
优化建议
当前每秒发送一次ping的频率过高,Heroku的流式响应空闲超时为55秒,你可以调整为每30秒发送一次ping,既能保证连接不会被平台断开,也能减少不必要的带宽和性能消耗。
内容的提问来源于stack exchange,提问作者Fred Hors
相关产品推荐
相关产品推荐

