猫鼬超时与 AWS DocumentDB 交谈

sti*_*mms 5 javascript mongoose serverless aws-documentdb

我们正在尝试在无服务器中构建在 Express 上的 lambda 中连接到 AWS DocumentDB。为此,我们使用 mongoose 和一个看起来像的连接函数

import mongoose from 'mongoose';
import logger from './utils/logger';
import fs from 'fs';

const READYSTATE_CONNECTED = 1;

const mongoDB = process.env.MONGODB_URI;

const certificateFilePath = __dirname + '/rds-combined-ca-bundle.pem';
logger.info(`Loading certificate file from ${certificateFilePath}`);
let ca = [fs.readFileSync(certificateFilePath)];


logger.info('Connection is ' + mongoose.connection.readyState);
if (mongoose.connection.readyState !== READYSTATE_CONNECTED) {
    logger.info(`Connecting to mongo using env connection string ${mongoDB}`);
    mongoose.connect(mongoDB, { useNewUrlParser: true, useUnifiedTopology: true, checkServerIdentity: false, ssl: true, sslCA: ca }).catch((err) => {
        logger.error(`Unable to connect to mongoose due to ${err.reason}`);
        console.error(err);
    });
}
mongoose.Promise = global.Promise;
const db = mongoose.connection;

// eslint-disable-next-line no-console
db.on('error', console.error.bind(console, 'MongoDB connection error:'));

export default db;
Run Code Online (Sandbox Code Playgroud)

这里的想法是我们维护一个连接并重用它以避免为进入 lambda 的每个请求创建新连接的费用。在大多数情况下,这工作正常,但每隔一段时间(可能每天 2 次),我们就会看到连接到数据库的问题。它似乎很难使 lambda 崩溃,我们必须触发 lambda 上的更改以诱使 lambda 重新启动我们的应用程序,然后再过几个小时一切正常。我们在 4 个相同的环境中运行,似乎生产环境是唯一遇到此问题的环境。生产比其他环境稍忙,但实际上只有 50%。

错误看起来像

2020-11-09T20:10:36.565Z d88c9b33-6b84-44cd-8c1d-297c6334aad5 ERROR MongooseServerSelectionError: connection timed out
at NativeConnection.Connection.openUri (/var/task/node_modules/mongoose/lib/connection.js:800:32)
at /var/task/node_modules/mongoose/lib/index.js:342:10
at /var/task/node_modules/mongoose/lib/helpers/promiseOrCallback.js:31:5
at new Promise (<anonymous>)
at promiseOrCallback (/var/task/node_modules/mongoose/lib/helpers/promiseOrCallback.js:30:10)
at Mongoose.connect (/var/task/node_modules/mongoose/lib/index.js:341:10)
at Object.<anonymous> (/var/task/src/mongoose.js:19:24)
at Module._compile (internal/modules/cjs/loader.js:1137:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1157:10)
at Module.load (internal/modules/cjs/loader.js:985:32)
at Function.Module._load (internal/modules/cjs/loader.js:878:14)
at Module.require (internal/modules/cjs/loader.js:1025:19)
at require (internal/modules/cjs/helpers.js:72:18)
at Object.<anonymous> (/var/task/src/AppBuilder.js:17:1)
at Module._compile (internal/modules/cjs/loader.js:1137:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1157:10) {
reason: TopologyDescription {
type: 'ReplicaSetNoPrimary',
setName: 'rs0',
maxSetVersion: null,
maxElectionId: null,
servers: Map {
'documentdbmasterinstance-xxxx.xxx.us-east-1.docdb.amazonaws.com:27017' => [ServerDescription],
'documentdbreplica1instance-xxxx.xxxx.us-east-1.docdb.amazonaws.com:27017' => [ServerDescription],
'documentdbreplica2instance-xxxx.xxxx.us-east-1.docdb.amazonaws.com:27017' => [ServerDescription]
},
stale: false,
compatible: true,
compatibilityError: null,
logicalSessionTimeoutMinutes: null,
heartbeatFrequencyMS: 10000,
localThresholdMS: 15,
commonWireVersion: 6
}
Run Code Online (Sandbox Code Playgroud)

到目前为止,我们一直无法查明导致这种情况的任何特定操作。当时与数据库的连接看起来确实略有增加,但只有大约 75 个连接,而且我们在 r5.large 上运行,它应该允许 1700 个连接,所以我们远远超出了这个限制。

我不确定ReplicaSetNoPrimary错误日志中提到的是否是一个红鲱鱼,但在类似的问题报告中似乎没有提到任何地方。我怀疑连接是否真的超时。所有 lambda 调用都不会超过 200 毫秒。

我想问题是:

  • 连接代码中是否有任何明显的原因会导致这种情况?
  • 在这个由 lambda 转换的快速应用程序中,是否有更好、更规范的方法来建立和维护连接?
  • 是否ReplicaSetNoPrimary表明 documentdb 选择新的主节点或主节点无法访问存在问题?
  • 我可以添加更多日志记录的任何建议以解决这个问题吗?

编辑:我们的连接字符串看起来像

mongodb://redacted:redacted@prod-db.cluster-cvgzkbo26lzb.us-east-1.docdb.amazonaws.com:27017/database?ssl=true&ssl_ca_certs=rds-combined-ca-bundle.pem&replicaSet=rs0&readPreference=secondaryPreferred&retryWrites=false
Run Code Online (Sandbox Code Playgroud)

小智 -2

连接超时可能有多种原因。最常见的原因是将您的 IP 地址列入白名单或启用公共访问,以便您可以访问数据库。

另一个原因可能是您正在使用的协议。有关更多信息,请分享连接字符串的格式,以便我可以相应地检查和更新我的答案。

  • 告诉某人向公众开放他们的数据库是非常糟糕的建议。 (5认同)