服务器上的活动连接数达到最大值

Number of active connections on the server reached to max

我正在使用 mongodb 和 nodejs。我在 Atlas 上托管了 mongodb。

我的后端一直运行良好,但现在有时会卡住,当我在 mongodb atlas 上看到分析时,它显示最大活动连接数达到 100.

有人可以解释为什么会这样吗?我可以重新启动连接并使其成为 0?

@Stennie 我用过 mongoose 连接数据库

这是我的配置文件

const mongooseOptions = {
  useNewUrlParser: true,
  autoReconnect: true,
  poolSize: 25,
  connectTimeoutMS: 30000,
  socketTimeoutMS: 30000
} 

exports.register = (server, options, next) => {
  defaults = Hoek.applyToDefaults(defaults, options)

  if (Mongoose.connection.readyState) {
    return next()
  }

  if (!Mongoose.connection.readyState) {
    server.log(`${process.env.NOED_ENV} server connecting to ${defaults.url} ${defaults.url}`)

    return Mongoose.connect(defaults.url, mongooseOptions).then(() => {
      return next() // call the next item in hapi bootstrap
    })
  }
}

假设您的后端部署在 lambda 上,因为无服务器标记。

每次调用都会让容器闲置以防止冷启动,或者使用现有容器(如果可用)。您正在打开连接以在调用之间重用它,如 best practices.

中所宣传的那样

poolSize 为 25 (?) 且最大连接数为 100,您应该将 function concurrency 限制为 4。

Reserve concurrency to prevent your function from using all the available concurrency in the region, or from overloading downstream resources.

更多阅读:https://www.mongodb.com/blog/post/optimizing-aws-lambda-performance-with-mongodb-atlas-and-nodejs

您可以尝试几件事:

  1. serverless 环境中,正如@Gabriel Bleu 已经建议的那样,为什么会有这么高的 connectionLimitServerless 环境不断生成新容器并根据请求停止。如果同时产生多个实例,它会很快耗尽 MongoDB 服务器限制。

  2. connectionPool的概念是,x每次从每个节点(实例)建立连接数。但这并不意味着所有连接在查询后都会自动释放。完成ALL DB操作后,应该release每个连接个体使用后:mongoose.connection.close();

注意:Mongoose connection close会关闭连接池的所有连接。所以理想情况下,这应该是 运行 就在返回响应之前。

  1. 为什么要将显式 autoReconnect 设置为 true。 MongoDB driver internally 会在连接丢失时重新连接,当然不建议用于 serverless containers.

  2. 等短寿命实例
  3. 如果您 运行 处于 cluster 模式,为了优化性能,将 serverUri 更改为副本集 URL 格式:MONGODB_URI=mongodb://<username>:<password>@<hostOne>,<hostTwo>,<hostThree>...&ssl=true&authSource=admin.

影响max connection limit的因素太多了。您有 mongoDB 托管在 Atlas 上,正如您提到的后端 lamda 意味着您有一个无服务器环境。

  1. 无服务器环境在新连接上生成新容器,并在不再使用时销毁连接。 peak 连接显示有太多新实例正在初始化或来自用户连接的并发请求太多。最佳做法是在不再需要时终止数据库连接。您可以终止连接 mongoose.connection.close(); 因为你用过 mongoose。它将从连接池中释放连接。与其耗尽并发连接限制,不如在连接空闲时释放连接。
  2. 您的配置强制数据库驱动程序在连接被数据库删除后重新连接。您显式地将 autoReconnect 设置为 true,这样驱动程序将在连接断开后快速实例化连接请求。这可能会影响 concurrent connection limit。您应该避免明确设置它。
  3. cluster mode可以根据负载优化请求,可以将服务器uri改为数据库副本。它可能有助于迁移负载。
  4. 首次调用 Lambda 函数并且 AWS Lambda 函数中的 MongoDB 客户端连接到 MongoDB 时,初始启动成本很小,大约需要 5 到 10 秒。连接到分片集群的 mongos 比连接到副本集更快。在 Lambda 函数的生命周期期间,后续连接将显着加快。所以每次调用都会让容器空闲以防止 cold startcold boot,或者使用现有容器(如果可用)。
  5. Atlas 根据集群层设置集群的并发传入连接限制。如果您在达到此限制时尝试连接,MongoDB 会显示一条错误消息“连接被拒绝,因为打开的连接太多”。您可以关闭当前未使用的与集群的任何打开连接。向下扩展到更高层以支持更多并发连接。如最佳实践中所述,您可以 restart 该应用程序。为防止将来出现此问题,请考虑使用 maxPoolSize 连接字符串选项来限制连接池中的连接数。
  6. 此问题的最终解决方案是升级到更大的 Atlas 集群层,从而允许更多连接。如果您的用户群对于您当前的集群层来说太大了。