部署到 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 正确打包您的模式。
部署到 AWS Lambda 的一般注意事项
本节介绍了您需要对应用程序进行的更改,无论使用何种框架。完成以下步骤后,请按照您所用框架的步骤操作。
在 Prisma 模式中定义二进制目标
根据 Node.js 的版本,您的 Prisma 模式应在 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
)可以访问正确的模式引擎。
对于 AWS lambda,您需要添加以下环境变量
PRISMA_CLI_BINARY_TARGETS=native,rhel-openssl-1.0.x
prisma migrate
是 prisma
包中的一个命令。通常,此包作为开发依赖项安装。根据您的设置,您可能需要将此包作为依赖项安装,以便将其包含在上传到 Lambda 并执行的包或存档中。
连接池
通常,当您使用函数即服务 (FaaS) 环境与数据库交互时,每次函数调用都可能导致与数据库的新连接。对于持续运行的 Node.js 服务器,这不成问题。因此,最好池化数据库连接以获得更好的性能。您可以使用 加速 来解决此问题。对于其他解决方案,请参阅 无服务器环境的连接管理指南。
使用 AWS SAM 部署
加载环境变量
AWS SAM 不直接支持从 .env
文件加载值。您必须使用 AWS 的一项服务来存储和检索这些参数。本指南 提供了有关您的选项以及如何在参数、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)
}
您还需要通过在 template.yaml
中的 Metadata.BuildProperties
中添加以下行来定义如何使用 esbuild 捆绑这些文件。
Loader:
- .prisma=file
- .so.node=file
AssetNames: '[name]'
这将确保 Prisma ORM 所需的文件包含在 AWS SAM 构建中。
使用 Serverless Framework 部署
通过 .env
文件加载环境变量
您的函数需要 DATABASE_URL
环境变量才能访问数据库。serverless-dotenv-plugin
插件允许您在部署中使用 .env
文件。
首先,确保已安装该插件。
npm install -D serverless-dotenv-plugin
然后,在 serverless.yml
中的插件列表中添加 serverless-dotenv-plugin
。
plugins:
- serverless-dotenv-plugin
现在,您的 .env
文件中的环境变量将在打包或部署时自动加载。
serverless package
仅部署所需的文件
为了减少部署占用空间,您可以更新部署流程,使其仅上传应用程序需要的文件。以下 serverless.yml
(Serverless 配置文件)显示了一个 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
存在,以确保查询根据您的模式进行编码和解码。在大多数情况下,捆绑器默认不会包含此文件,这会导致您的应用程序无法运行。
根据应用程序的捆绑方式,您可能需要将模式复制到 ./
以外的位置。使用 serverless package
命令在本地打包代码,以便您可以查看应将模式放在哪里。
有关其他配置,请参阅 Serverless Webpack 文档。
3. 更新 serverless.yml
在您的 serverless.yml
文件中,确保 custom > webpack
块在 packagerOptions > scripts
下具有 prisma generate
,如下所示。
custom:
webpack:
packagerOptions:
scripts:
- prisma generate
这将确保在 webpack 捆绑您的代码后,根据您的模式生成 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
移动的模式。
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