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

Golang并行POST请求未生效:耗时远超预期问题排查

问题分析与解决方案

你的代码虽用goroutine发起请求,但实际未实现真正并行,总耗时远超预期,核心原因是Go标准库http.Client的默认连接池限制了单主机并发连接数,导致请求排队执行。

具体原因

Go的http.Transport默认配置中,MaxConnsPerHost(单主机最大并发连接数)默认值为2(部分版本可能调整,但早期版本均为此限制)。若所有请求发往同一目标主机,同一时间最多仅2个请求能执行,其余请求会阻塞等待连接释放,这就造成了你看到的请求分批返回、总耗时被拉长的现象——从日志能明显看出请求并非同时完成,而是间隔数秒到十数秒分批返回,完全符合连接池排队的特征。

解决步骤

1. 自定义HTTP客户端,调整连接池参数

修改types.PostJSON使用的HTTP客户端,增大单主机并发连接数:

// 自定义Transport,调整连接池参数
customTransport := &http.Transport{
    MaxConnsPerHost: 100, // 设置与provider数量匹配的并发数
    MaxIdleConns:    100,
    IdleConnTimeout: 30 * time.Second,
}

// 创建自定义客户端
client := &http.Client{
    Transport: customTransport,
    Timeout:   10 * time.Second, // 设置合理请求超时
}

确保types.PostJSON内部使用该自定义client发起请求,而非默认的http.DefaultClient。

2. 改用带缓冲的Channel优化goroutine执行

当前代码使用无缓冲Channel,goroutine执行到ch <- response时会阻塞至主goroutine接收值。改为带缓冲的Channel可避免不必要的阻塞,让goroutine更快完成执行:

// 创建缓冲大小等于provider数量的Channel
ch := make(chan models.SocketResource, len(providers))

3. 补充错误处理(可选但关键)

代码中忽略了PostJSON和json.Unmarshal的错误,可能隐藏请求失败问题,建议添加处理逻辑:

func process(
    provider models.Provider, 
    query models.Query, 
    db *sql.DB, 
    ch chan<- models.SocketResource
) {
    body, raw, err := types.PostJSON(urlStr, string(jsonData), map[string]string{"Content-Type": "application/json"}, types.Proxy{}, jar)
    if err != nil {
        log.Printf("请求provider %s失败: %v", provider.Name, err)
        ch <- models.SocketResource{} // 发送空值避免主goroutine阻塞
        return
    }
    response := models.RequestAnswers{}
    err = json.Unmarshal([]byte(body), &response)
    if err != nil {
        log.Printf("解析响应失败: %v", err)
        ch <- models.SocketResource{}
        return
    }
    ch <- response
}

验证效果

修改后,所有请求将真正并行执行,总耗时会接近单个请求的最长响应时间(即你预期的5秒左右),而非所有请求耗时的累加。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 12:35:31