使用 mongo.Connect 时连接未打开,而是在我执行查询时打开

分享于2022年07月17日 go mongo-go mongodb 问答
【问题标题】:使用 mongo.Connect 时连接未打开,而是在我执行查询时打开(Connection is not open when use mongo.Connect instead it does when I do the query)
【发布时间】:2022-01-18 11:48:33
【问题描述】:

我正在编写一个使用 mongo-driver 连接到 mongo 副本集的 Go 应用程序。

我注意到 mongo.Connect 实际上并没有连接到数据库。

即使我关闭了 mongod 实例, mongo.Connect 仍然可以通过。

但是,当我进行查询时,它将连接到 mongod 实例。

现在我的问题是我在同一个 mongod 实例中对不同数据库有很多 (>100) 个并发查询。

驱动程序创建了一大堆连接, mongod 让我失败了 Too many files opened ,因为连接太多,即使我只使用一个 mongo.Client

这是 mongo_driver 的正确行为吗?我该如何处理?

MongoDB 是否需要每个数据库的每个连接?


【解决方案1】:

mongo.Connect() 创建一个新的 mongo.Client 并对其进行初始化,但不会(必然)创建到数据库服务器的连接。

要实际创建连接并检查服务器是否可达(不执行查询),您可以使用 Client.Ping() 方法。如果服务器不可访问,这将返回错误。

官方的 mongodb 驱动管理一个内部连接池。连接在使用后不会立即关闭,而是将它们放回池中,因此当需要连接来执行操作时,可以立即使用池中的空闲连接。这是预期的行为。您可以通过传递给 mongo.Connect() options.ClientOptions 配置其大小。

ClientOptions.SetMaxPoolSize() :

SetMaxPoolSize 指定驱动程序的连接池中允许到每个服务器的最大连接数。如果达到此最大值,对服务器的请求将被阻止。这也可以通过“maxPoolSize”URI 选项设置(例如“maxPoolSize=100”)。默认为 100。如果为 0,则设置为 math.MaxInt64。

设置连接受限的客户端并对其进行 ping 操作的示例:

ctx := context.Background()

opts := options.Client().
    ApplyURI("mongodb://localhost").
    SetMaxPoolSize(20) // Allow no more than 20 connections per server

client, err := mongo.Connect(ctx, opts)
if err != nil {
    log.Printf("mongo.Connect() failed: %v", err)
    return
}
defer client.Disconnect(ctx)

if err := client.Ping(ctx, nil); err != nil {
    log.Printf("Can't connect to db: %v", err)
    return
}

// Use client

查看相关: goroutine create multiple mongodb connection