【问题标题】:Number of active connections on the server reached to max服务器上的活动连接数达到最大值
【发布时间】:2019-10-15 19:57:21
【问题描述】:

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

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

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

@Stennie我用猫鼬连接数据库

这是我的配置文件

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
    })
  }
}

【问题讨论】:

    标签: node.js mongodb mongoose serverless-framework replicaset


    【解决方案1】:

    假设你的后端部署在 lambda 上,因为 serverless 标记。

    每次调用都会让容器处于空闲状态以防止冷启动,或者使用现有的容器(如果可用)。您将打开连接以在调用之间重用它,就像在 best practices 中宣传的那样。

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

    保留并发以防止您的函数使用该区域中的所有可用并发,或防止下游资源过载。

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

    【讨论】:

    • 是的,我的后端在 lambda 上。好吧,我不能从上面的答案中得到什么,但据我所知“每个部署命令都会创建一个新的 mongo 连接!!!”那么我可以sudo serverless remove -s <stag> 命令停止和启动我的服务吗?这样所有现有的连接都会中断吗?
    • 不是部署而是调用,每个容器应该在大约 30 分钟不活动后被删除,mongo 服务器应该在一定的超时后自行释放会话。如果您想手动释放陈旧的连接,您应该能够使用 Compas 或命令行杀死那些连接。
    【解决方案2】:

    你可以尝试几件事:

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

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

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

    1. 你为什么要将明确的 autoReconnect 设置为 true。 MongoDB driver internally 会在连接丢失时重新连接,当然不建议将其用于serverless containers 等生命周期较短的实例。

    2. 如果您在 cluster 模式下运行,为了优化性能,请将 serverUri 更改为副本集 URL 格式:MONGODB_URI=mongodb://<username>:<password>@<hostOne>,<hostTwo>,<hostThree>...&ssl=true&authSource=admin

    【讨论】:

    • #2 你的意思是每个查询本身都会建立一个新的连接?
    • 没有。当您将connectionLimit 设置为 25(默认为 5)时,所有 25 个connections 都会打开(相对于serverQuota-此处为 100)到服务器(活动连接),即使请求不多。并且一旦打开connections,对于每个查询,将仅使用来自所述池的连接。如果所有 25 个连接都被查询耗尽,那么第 26 个查询将不得不等到25 queries 之一释放(而不是关闭)连接。因此,除非您正在制作 25 parallel queries(请注意 NodeJ 的异步性质),否则对于如此高的限制来说,它并不适用。
    • @Profer 每个查询都不会启动新连接,但将使用先前保留的旧连接,这里的故障是查询之间会有一点时间,因此连接将处于空闲状态时间。而不是让它保持空闲,最好在查询完成后终止连接,这样它就不会耗尽连接池
    【解决方案3】:

    影响max connection limit的因素有很多。您在 Atlas 上托管了 mongoDB,正如您提到的后端是 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 集群层。如果您的用户群对于您当前的集群层来说太大。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-13
      • 1970-01-01
      • 2015-05-27
      • 2023-03-22
      • 1970-01-01
      • 2018-07-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多