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

Mongo Go Driver并发请求响应延迟过高,求原因排查与优化方案

问题描述

我搭建了一个基于MongoDB持久化的REST API,在持续负载测试中(每秒100个请求)发现响应时长逐渐攀升,排查后确认是MongoDB查询耗时增加,最高达到2秒。测试的是一个简单的GET数据列表接口,使用mongo-go-driver v2版本、Go 1.23.1,数据库部署在Mongo Atlas免费版。尝试调整连接池大小、缩短连接超时时间后问题仍未解决,想明确该现象是Mongo并发连接的正常情况、代码配置有误,还是Mongo Atlas免费版的性能瓶颈?

MongoDB连接代码

package app

import (
    "context"
    "log"
    "time"

    "go.mongodb.org/mongo-driver/v2/mongo"
    "go.mongodb.org/mongo-driver/v2/mongo/options"
)

var mongoClient *mongo.Client
var DatabaseName string

func init() {
    connectionTimeOut := 5 * time.Second
    mongoUri := GetConfig().MongoUri
    DatabaseName = GetConfig().DatabaseName

    clientOptions := options.Client().ApplyURI(mongoUri)
    clientOptions.SetMaxPoolSize(100) // Adjust as needed
    clientOptions.SetMinPoolSize(10)
    clientOptions.SetConnectTimeout(connectionTimeOut)

    tempClient, err := mongo.Connect(clientOptions)
    if err != nil {
        log.Fatal(err)
    }

    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancel()

    log.Println("Connecting to MongoDB...")

    err = tempClient.Ping(ctx, nil)
    if err != nil {
        log.Fatal(err)
    }

    mongoClient = tempClient

    log.Println("Connected to MongoDB!")
}

func DisconnectMongoClient() {
    mongoClient.Disconnect(context.Background())
}

func GetMongoCollection(collectionName string) *mongo.Collection {
    return mongoClient.Database(DatabaseName).Collection(collectionName)
}

数据查询代码

type BotRepository struct {
    mongoColl *mongo.Collection
}

func NewBotRepository() *BotRepository {
    return &BotRepository{
        mongoColl: app.GetMongoCollection(app.BotCollection),
    }
}

func (r *BotRepository) GetBotsList() ([]*dtos.Bot, error) {
    cursor, err := r.mongoColl.Find(context.TODO(), bson.M{})

    if err != nil {
        return nil, err
    }

    defer cursor.Close(context.TODO())

    var bots []*dtos.Bot

    for cursor.Next(context.TODO()) {
        var raw bson.M
        if err := cursor.Decode(&raw); err != nil {
            log.Error(err)
        }

        id := raw["_id"].(bson.ObjectID).Hex()

        var bot *dtos.Bot
        if err := cursor.Decode(&bot); err != nil {
            log.Error(err)
            continue
        }
        bot.Id = id
        bots = append(bots, bot)
    }

    return bots, nil
}

问题分析与解决建议

1. 代码层面的核心错误

查询代码存在重复解码的严重问题:在cursor.Next()循环中,你先把当前文档解码到raw bson.M,接着又调用cursor.Decode(&bot)——这会尝试解码下一个文档,导致数据错位,同时额外消耗CPU和MongoDB的网络带宽,直接拉低查询效率,延迟会随并发量放大。

修复后的代码示例:

func (r *BotRepository) GetBotsList() ([]*dtos.Bot, error) {
    cursor, err := r.mongoColl.Find(context.TODO(), bson.M{})
    if err != nil {
        return nil, err
    }
    defer cursor.Close(context.TODO())

    var bots []*dtos.Bot
    for cursor.Next(context.TODO()) {
        var bot dtos.Bot
        if err := cursor.Decode(&bot); err != nil {
            log.Error(err)
            continue
        }
        // 直接从解码后的结构体获取_id并转字符串
        bot.Id = bot.ID.Hex() // 假设dtos.Bot定义了bson.ObjectID类型的ID字段对应数据库_id
        bots = append(bots, &bot)
    }

    // 必须检查cursor遍历后的错误
    if err := cursor.Err(); err != nil {
        log.Error(err)
        return nil, err
    }

    return bots, nil
}

2. MongoDB Atlas免费版的硬限制

Mongo Atlas M0沙箱实例有严格的资源约束:

  • 共享CPU/内存资源,并发请求增多时会被限流
  • 最大连接数限制为50(你的连接池设置MaxPoolSize=100已超出上限,导致连接排队)
  • 网络带宽有限,跨区域访问延迟更高

每秒100个请求已经远超M0实例的承载能力,持续负载下必然出现查询延迟攀升。

3. 连接池配置优化

  • 将MaxPoolSize调整为40-45,低于M0的50连接上限,避免客户端侧连接排队
  • 连接超时从5秒缩短至1-2秒,减少无效等待时间
  • 可以添加SetMaxConnIdleTime配置,释放闲置连接,避免资源浪费

4. 查询性能优化

  • 当前查询是全表扫描Find(bson.M{}),即使是小集合,并发下也会消耗大量资源,建议根据业务需求添加合适的索引
  • 添加分页逻辑,用FindOptions().SetLimit()和SetSkip()限制单次返回数据量,降低数据库和网络负载
  • 替换context.TODO()为context.WithTimeout,给每个查询设置合理超时(比如1秒),避免慢查询占用连接资源

结论

问题是代码错误+Mongo Atlas免费版资源限制共同导致的:

  1. 重复解码的代码错误直接降低查询效率,放大延迟
  2. M0实例无法支撑每秒100个并发请求的持续负载
  3. 连接池配置超出实例最大连接数,加剧排队延迟

建议先修复代码问题,调整连接池参数,同时降低并发测试量(比如每秒20-30个请求)验证效果。若需更高并发能力,需升级到Atlas付费实例(如M10)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 14:25:56