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

如何排查Golang GraphQL订阅API仅返回第一条数据的问题?

问题原因及解决方案

核心原因

你的订阅连接在发送第一条消息后被提前终止,触发ctx.Done()分支,主要诱因有两个:

  • GCP负载均衡的空闲超时机制:GCP HTTP(S)负载均衡默认空闲连接超时为30秒,若消息发送无间隔、传输层未维持长连接活跃,负载均衡会主动断开连接,进而取消请求上下文。
  • SSE传输的兼容性问题:若gqlgen默认使用Server-Sent Events(SSE)作为订阅传输,GCP部分环境对SSE长连接的支持有限,易被中途断开。

解决方案

1. 添加消息发送间隔,维持连接活跃

在循环中加入短暂延迟,模拟真实场景的消息节奏,避免连接被判定为空闲:

func (r *subscriptionResolver) CreateChatWithBot(ctx context.Context, req model.CreateChatWithBotRequest) (<-chan *model.CreateChatWithBotResults, error) {
    ch := make(chan *model.CreateChatWithBotResults)

    testString := []string{"This", "part", "is", "under", "construction", "...", " Be", "patient", "please!"}
    go func() {
        defer close(ch)
        for _, v := range testString {    
            select {
            case <-ctx.Done():
                return
            case ch <- &model.CreateChatWithBotResults{Response: pointer.Pointer(v)}:
                // 添加1秒延迟,维持连接活跃
                time.Sleep(1 * time.Second)
            }
        }
    }()
    return ch, nil
}

2. 切换为WebSocket传输协议

相比SSE,WebSocket在GCP环境下的长连接稳定性更强。修改gqlgen服务配置启用WebSocket:

func main() {
    c := config.DefaultConfig()
    // 其他配置代码...
    srv := handler.NewDefaultServer(generated.NewExecutableSchema(c))
    
    // 启用WebSocket订阅支持
    srv.AddTransport(transport.Websocket{
        Upgrader: websocket.Upgrader{
            CheckOrigin: func(r *http.Request) bool {
                // 根据业务需求配置跨域规则
                return true
            },
        },
    })
    
    // 启动服务代码...
}

之后在Postman中使用WebSocket方式调用订阅API,替代原HTTP请求方式。

3. 调整GCP负载均衡超时设置

若前两种方法无效,可在GCP控制台延长负载均衡的空闲超时:

  • 进入负载均衡页面,找到目标实例
  • 编辑后端服务,将“空闲超时”参数调整为更长时间(最长支持86400秒)

验证顺序

  1. 先测试添加消息延迟的方案,确认是否能接收全部消息
  2. 若问题依旧,切换到WebSocket传输协议
  3. 最后考虑调整GCP负载均衡的超时配置

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 02:55:03