部署到 AWS Lambda
本指南解释了如何在使用 Prisma ORM 部署项目到 AWS Lambda 时避免常见问题。
虽然部署到 AWS Lambda 不需要部署框架,但本指南涵盖了使用以下框架进行部署:
- AWS Serverless Application Model (SAM) 是 AWS 的开源框架,可用于创建无服务器应用程序。AWS SAM 包括 AWS SAM CLI,您可以使用它来构建、测试和部署您的应用程序。
- Serverless Framework 提供了一个 CLI,可以帮助您进行工作流自动化和 AWS 资源配置。虽然 Prisma ORM 可以与 Serverless Framework “开箱即用”地良好配合,但在您的项目中可以进行一些改进,以确保顺利部署和性能。如果您正在使用
serverless-webpack
或serverless-bundle
库,则需要额外的配置。 - SST 提供了使开发人员可以轻松定义、测试、调试和部署其应用程序的工具。Prisma ORM 可以与 SST 良好配合使用,但必须进行配置,以便 SST 正确打包您的 schema。
部署到 AWS Lambda 的一般注意事项
本节介绍了无论使用何种框架,您都需要对应用程序进行的更改。完成这些步骤后,请按照您的框架的步骤进行操作。
在 Prisma Schema 中定义二进制目标
根据 Node.js 的版本,您的 Prisma schema 应在 generator
块中包含 rhel-openssl-1.0.x
或 rhel-openssl-3.0.x
- Node.js 16 和 18
- Node.js 20+
binaryTargets = ["native", "rhel-openssl-1.0.x"]
binaryTargets = ["native", "rhel-openssl-3.0.x"]
这是必要的,因为开发和部署中使用的运行时不同。添加 binaryTarget
以使兼容的 Prisma ORM 引擎文件可用。
具有 arm64 架构的 Lambda 函数
使用 arm64 架构(AWS Graviton2 处理器) 的 Lambda 函数必须使用 arm64
预编译引擎文件。
在您的 schema.prisma
文件的 generator
块中,添加以下内容
binaryTargets = ["native", "linux-arm64-openssl-1.0.x"]
Prisma CLI 二进制目标
虽然我们不建议在 AWS Lambda 中运行迁移,但某些应用程序将需要这样做。在这些情况下,您可以使用 PRISMA_CLI_BINARY_TARGETS 环境变量来确保 Prisma CLI 命令(包括 prisma migrate
)可以访问正确的 schema 引擎。
对于 AWS lambda,您将必须添加以下环境变量
PRISMA_CLI_BINARY_TARGETS=native,rhel-openssl-1.0.x
prisma migrate
是 prisma
包中的一个命令。通常,此包作为开发依赖项安装。根据您的设置,您可能需要将此包作为依赖项安装,以便将其包含在上传到 Lambda 并执行的捆绑包或存档中。
连接池
通常,当您使用函数即服务 (FaaS) 环境与数据库交互时,每个函数调用都可能导致与数据库建立新连接。这对于持续运行的 Node.js 服务器来说不是问题。因此,对数据库连接进行池化以获得更好的性能是有益的。您可以使用 Accelerate 来解决此问题。对于其他解决方案,请参阅 无服务器环境的连接管理指南。
使用 AWS SAM 部署
加载环境变量
AWS SAM 不直接支持从 .env
文件加载值。您将必须使用 AWS 的服务之一来存储和检索这些参数。本指南 提供了关于您的选项以及如何在 Parameters、SSM、Secrets Manager 等中存储和检索值的出色概述。
加载所需文件
AWS SAM 使用 esbuild 来捆绑您的 TypeScript 代码。但是,未公开完整的 esbuild API,并且不支持 esbuild 插件。当在您的应用程序中使用 Prisma ORM 时,这会导致问题,因为某些文件(如 schema.prisma
)必须在运行时可用。
为了解决这个问题,您需要在代码中直接引用所需的文件,以便正确地捆绑它们。在您的应用程序中,您可以将以下行添加到实例化 Prisma ORM 的应用程序中。
import schema from './prisma/schema.prisma'
import x from './node_modules/.prisma/client/libquery_engine-rhel-openssl-1.0.x.so.node'
if (process.env.NODE_ENV !== 'production') {
console.debug(schema, x)
}
使用 Serverless Framework 部署
通过 .env
文件加载环境变量
您的函数将需要 DATABASE_URL
环境变量来访问数据库。serverless-dotenv-plugin
将允许您在部署中使用 .env
文件。
首先,确保已安装该插件
npm install -D serverless-dotenv-plugin
然后,将 serverless-dotenv-plugin
添加到 serverless.yml
中的插件列表中
plugins:
- serverless-dotenv-plugin
现在,.env
文件中的环境变量将在打包或部署时自动加载。
serverless package
仅部署所需文件
为了减少您的部署占用空间,您可以更新您的部署流程,使其仅上传应用程序所需的文件。下面的 Serverless 配置文件 serverless.yml
显示了一个 package
模式,该模式仅包含与 Lambda 运行时相关的 Prisma ORM 引擎文件,并排除其他文件。这意味着当 Serverless Framework 打包您的应用程序以进行上传时,它仅包含一个引擎文件。这确保了打包的存档尽可能小。
package:
patterns:
- '!node_modules/.prisma/client/libquery_engine-*'
- 'node_modules/.prisma/client/libquery_engine-rhel-*'
- '!node_modules/prisma/libquery_engine-*'
- '!node_modules/@prisma/engines/**'
- '!node_modules/.cache/prisma/**' # only required for Windows
如果您要部署到具有 ARM64 架构的 Lambda 函数,则应更新 Serverless 配置文件以打包 arm64
引擎文件,如下所示
package:
patterns:
- '!node_modules/.prisma/client/libquery_engine-*'
- 'node_modules/.prisma/client/libquery_engine-linux-arm64-*'
- '!node_modules/prisma/libquery_engine-*'
- '!node_modules/@prisma/engines/**'
如果您使用 serverless-webpack
,请参阅下面的使用 serverless webpack 部署。
使用 serverless-webpack
部署
如果您使用 serverless-webpack
,则需要额外的配置,以便正确捆绑您的 schema.prisma
。您将需要:
- 使用
copy-webpack-plugin
复制您的schema.prisma
。 - 在
serverless.yml
中通过custom > webpack > packagerOptions > scripts
运行prisma generate
。 - 仅打包正确的 Prisma ORM 引擎文件,以节省超过 40mb 的容量。
1. 安装 webpack 特定依赖项
首先,确保已安装以下 webpack 依赖项
npm install --save-dev webpack webpack-node-externals copy-webpack-plugin serverless-webpack
2. 更新 webpack.config.js
在您的 webpack.config.js
中,确保您将 externals
设置为 nodeExternals()
,如下所示
const nodeExternals = require('webpack-node-externals')
module.exports = {
// ... other configuration
externals: [nodeExternals()],
// ... other configuration
}
更新 webpack.config.js
文件中的 plugins
属性以包含 copy-webpack-plugin
const nodeExternals = require('webpack-node-externals')
const CopyPlugin = require('copy-webpack-plugin')
module.exports = {
// ... other configuration
externals: [nodeExternals()],
plugins: [
new CopyPlugin({
patterns: [
{ from: './node_modules/.prisma/client/schema.prisma', to: './' }, // you may need to change `to` here.
],
}),
],
// ... other configuration
}
此插件将允许您将 schema.prisma
文件复制到您的捆绑代码中。Prisma ORM 要求您的 schema.prisma
存在,以确保根据您的 schema 对查询进行编码和解码。在大多数情况下,捆绑器默认情况下不会包含此文件,并且会导致您的应用程序无法运行。
根据您的应用程序的捆绑方式,您可能需要将 schema 复制到 ./
以外的位置。使用 serverless package
命令在本地打包您的代码,以便您可以查看应将 schema 放置在何处。
有关其他配置,请参阅 Serverless Webpack 文档。
3. 更新 serverless.yml
在您的 serverless.yml
文件中,确保 custom > webpack
块在 packagerOptions > scripts
下具有 prisma generate
,如下所示
custom:
webpack:
packagerOptions:
scripts:
- prisma generate
这将确保在 webpack 捆绑您的代码后,根据您的 schema 生成 Prisma Client。没有此步骤,您的应用程序将无法运行。
最后,您将需要排除与 AWS Lambda 运行时不匹配的 Prisma ORM 查询引擎。通过添加以下脚本来更新您的 serverless.yml
,该脚本确保最终打包的存档中仅包含所需的查询引擎 rhel-openssl-1.0.x
。
custom:
webpack:
packagerOptions:
scripts:
- prisma generate
-- find . -name "libquery_engine-*" -not -name "libquery_engine-rhel-openssl-*" | xargs rm
如果您要部署到具有 ARM64 架构的 Lambda 函数,则应将 find
命令更新为以下内容
custom:
webpack:
packagerOptions:
scripts:
- prisma generate
-- find . -name "libquery_engine-*" -not -name "libquery_engine-arm64-openssl-*" | xargs rm
4. 总结
您现在可以重新打包并重新部署您的应用程序。为此,请运行 serverless deploy
。Webpack 输出将显示使用 copy-webpack-plugin
移动的 schema
serverless package
使用 SST 部署
使用环境变量
虽然 SST 支持 .env
文件,但不建议这样做。SST 建议使用 Config
以安全的方式访问这些环境变量。
此处提供的 SST 指南 是开始使用 Config
的分步指南。假设您已创建了一个名为 DATABASE_URL
的新密钥,并将该密钥绑定到您的应用程序,您可以使用以下代码设置 PrismaClient
import { PrismaClient } from '@prisma/client'
import { Config } from 'sst/node/config'
const globalForPrisma = global as unknown as { prisma: PrismaClient }
export const prisma =
globalForPrisma.prisma ||
new PrismaClient({
datasourceUrl: Config.DATABASE_URL,
})
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
export default prisma