You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go语言实现每2秒触发SSE遇延迟问题求助

解决Go语言SSE服务每2秒稳定推送数据的问题

问题根源分析

  1. 原始代码仅推送一次就断开连接:你的初始handleSse函数只发送一次数据就结束,客户端EventSource发现连接断开后会自动重连(默认重连间隔约3秒),叠加网络延迟后就出现了你看到的5.4秒间隔——这并非服务端主动推送的间隔,而是客户端重连的间隔。
  2. 尝试的循环写法逻辑错误:你写的循环会瞬间完成10次数据推送,客户端一次性接收所有数据后连接断开,再次触发重连;添加time.Sleep后,整个handler会阻塞执行完所有循环,期间客户端无法收到分段数据,且连接关闭后重连间隔进一步累积,导致总延迟变长。

修正后的服务端代码

package main

import (
    "fmt"
    "log"
    "net/http"
    "time"

    "github.com/rs/cors"
)

func main() {
    mux := http.NewServeMux()

    mux.HandleFunc("/sse", handleSse)

    c := cors.New(cors.Options{
        AllowedOrigins:   []string{"*"},
        AllowedMethods:   []string{http.MethodGet, http.MethodPost, http.MethodDelete, http.MethodPut},
        AllowCredentials: true,
    })

    handler := c.Handler(mux)

    log.Fatal(http.ListenAndServe(":6969", handler))
}

func handleSse(w http.ResponseWriter, r *http.Request) {
    // 设置SSE响应头
    w.Header().Set("Content-Type", "text/event-stream")
    w.Header().Set("Cache-Control", "no-cache")
    w.Header().Set("Connection", "keep-alive")

    // 断言获取Flusher接口,用于强制刷新缓冲区
    f, ok := w.(http.Flusher)
    if !ok {
        http.Error(w, "SSE not supported", http.StatusBadRequest)
        return
    }

    // 监听客户端断开信号,避免goroutine泄漏
    ctx := r.Context()
    // 创建2秒间隔的定时器
    ticker := time.NewTicker(2 * time.Second)
    defer ticker.Stop()

    for {
        select {
        case <-ctx.Done():
            // 客户端断开连接,退出循环释放资源
            return
        case <-ticker.C:
            // 发送符合SSE规范的数据(格式:data: 内容\n\n)
            fmt.Fprintf(w, "data: %v\n\n", time.Now().Format("2006-01-02 15:04:05"))
            // 强制刷新缓冲区,确保数据立即推送给客户端
            f.Flush()
        }
    }
}

关键修正点说明

  • 定时推送+长连接保持:使用time.Ticker实现精准的2秒间隔推送,替代循环+sleep的阻塞式写法,保证handler不会被长时间占用。
  • 监听客户端断开:通过r.Context().Done()实时感知客户端连接关闭事件,及时退出循环,避免服务端goroutine泄漏。
  • 严格遵循SSE格式:保持data: 内容\n\n的标准格式,确保客户端EventSource能正确解析推送内容。
  • 强制刷新缓冲区:每次发送数据后调用f.Flush(),避免Go HTTP缓冲区积压数据,确保消息实时推送给客户端。

客户端验证调整

可修改客户端onmessage回调打印具体数据,确认推送间隔:

event.onmessage = (e) => {
    console.log("收到推送:", e.data);
};

运行服务后,客户端控制台会每2秒打印一条带时间戳的数据,实现稳定的SSE推送效果。

内容的提问来源于stack exchange,提问作者yahya kamran

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 11:40:06