Vercel 为每个请求创建新的数据库连接

Kam*_*ari 3 mongoose mongodb mongodb-atlas vercel sapper

我正在开发一个新网站,虽然我们在本地开发时一切正常,但当我们尝试在 Vercel 上部署时遇到了问题。该应用程序为页面和 API 使用 Sapper 框架,以及我们通过 Mongoose 访问的 MongoDB Atlas 中的数据库。我们在本地的行为是我们建立npm run dev了一个单一的数据库连接,该连接一直持续到我们关闭应用程序。

本地日志

但是,当它被部署到 Vercel 时,建立数据库连接并打印“数据库连接成功”消息并且只应该运行一次的代码会在每个 API 请求上运行

每个请求的新数据库连接

这似乎很快就失控了,达到了我们数据库 500 个连接的限制: 数据库连接达到限制

结果,在网站被一个用户短暂使用后,我们的一些 API 请求开始失败并出现此错误(我们让 db 接受任何连接而不是 IP 白名单,因此错误给出的建议没有帮助) : API 无法连接到数据库

我们的实现是mongoose.connect在 .js 文件中调用:

mongoose.connect(DB, {
    useNewUrlParser: true,
    useCreateIndex: true,
    useFindAndModify: false,
    useUnifiedTopology: true
}).then(() => console.log("DB connection successful!")).catch(console.error);
Run Code Online (Sandbox Code Playgroud)

然后我们import在 Sapper 的server.js. 我们能够找到的建议是“只缓存连接”,但这并没有成功,而且似乎更重要node-mongodb-native。无论如何,这是我们尝试过的,在本地没有更好或更糟的效果,但也没有解决 Vercel 上的问题:

let cachedDb = {};

exports.connection = async () => {
    if (cachedDb.isConnected)
        return;
        try {
            const db = await mongoose.connect(DB, {
                            useNewUrlParser: true,
                            useCreateIndex: true,
                            useFindAndModify: false,
                            useUnifiedTopology: true
                        });
            cachedDb.isConnected = db.connections[0].readyState;
            console.log("DB connection successful!");
            return cachedDb;
        } catch(error) {console.log("Couldn't connect to DB", error);}
Run Code Online (Sandbox Code Playgroud)

那么......有没有一种方法可以在不更换至少一个部件的情况下完成这项工作?该网站尚未上线,因此更换某些内容并不是世界末日,但“只是更改设置”绝对比从头开始更受欢迎。

pau*_*gdm 5

概括

Vercel 上的无服务器功能就像一个独立的过程。虽然可以“按功能”缓存连接,但将 serverful-ready 库部署到无服务器环境并不是一个好主意。以下是您需要回答的几个问题:

  • 您的框架或数据库库是否缓存了连接?
  • 您的代码是否为 Serverless 做好了准备?
  • Vercel 针对什么类型的工作负载进行了优化?

进一步的背景

Vercel 是一个出色的前端平台,可以使用 Serverless Functions 作为助手。CDN 可与工作流结合使用,使部署过程非常快速,并允许您更快地移动。部署成熟的 API 或服务器负载永远不是一个好主意。假设我需要在 Vercel 中使用 MySQL。您应该使用mysql-serverless而不是mysql,它针对无服务器原语进行了优化。即使考虑到这一点,根据您期望的请求级别,仅将 VM/容器用于 API 可能会更便宜。因此,我们最终会得到以下理想的解决方案:

Frontend (Vercel - Serverless) --> Backend (Serverful - External provider) --> DB
Run Code Online (Sandbox Code Playgroud)

免责声明:目前,我为 Vercel 工作。