跳到主內容

部署到 AWS Lambda

本指南解釋了將使用 Prisma ORM 的專案部署到 AWS Lambda 時如何避免常見問題。

儘管部署框架不是部署到 AWS Lambda 的必需品,但本指南涵蓋了以下部署方式:

  • AWS 無伺服器應用模型 (SAM) 是 AWS 的一個開源框架,可用於建立無伺服器應用程式。AWS SAM 包含 AWS SAM CLI,你可以用它來構建、測試和部署你的應用程式。
  • Serverless Framework 提供了一個 CLI,有助於工作流自動化和 AWS 資源預置。儘管 Prisma ORM 可以“開箱即用”地與 Serverless Framework 很好地配合,但你的專案中仍可以進行一些改進,以確保順利部署和良好效能。如果你使用 serverless-webpackserverless-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`。

binaryTargets = ["native", "rhel-openssl-1.0.x"]

這是必需的,因為開發和部署中使用的執行時不同。新增 binaryTarget 以使相容的 Prisma ORM 引擎檔案可用。

使用 arm64 架構的 Lambda 函式

使用 arm64 架構(AWS Graviton2 處理器) 的 Lambda 函式必須使用 `arm64` 預編譯引擎檔案。

在你的 `schema.prisma` 檔案的 `generator` 塊中,新增以下內容

schema.prisma
binaryTargets = ["native", "linux-arm64-openssl-1.0.x"]

Prisma CLI 二進位制目標

儘管我們不建議在 AWS Lambda 中執行遷移,但某些應用程式會需要它。在這種情況下,你可以使用 PRISMA_CLI_BINARY_TARGETS 環境變數來確保 Prisma CLI 命令(包括 `prisma migrate`)能夠訪問正確的 schema 引擎。

對於 AWS Lambda,你需要新增以下環境變數

.env
PRISMA_CLI_BINARY_TARGETS=native,rhel-openssl-1.0.x
資訊

`prisma migrate` 是 `prisma` 包中的一個命令。通常,此包作為開發依賴項安裝。根據你的設定,你可能需要將其作為生產依賴項安裝,以便它包含在上傳到 Lambda 並執行的捆綁包或歸檔檔案中。

連線池

在函式即服務 (FaaS) 環境中,每次函式呼叫通常都會建立一個新的資料庫連線。與持續執行的 Node.js 伺服器不同,這些連線在執行之間不會保持。為了在無伺服器環境中獲得更好的效能,請實現連線池以重用現有資料庫連線,而不是為每個函式呼叫建立新連線。

你可以使用 Accelerate 進行連線池,或使用內建連線池的 Prisma Postgres 來解決此問題。有關其他解決方案,請參閱無伺服器環境的連線管理指南

使用 AWS SAM 部署

載入環境變數

AWS SAM 不直接支援從 `.env` 檔案載入值。你必須使用 AWS 的服務之一來儲存和檢索這些引數。本指南 提供了關於你的選項以及如何在 Parameters、SSM、Secrets Manager 等中儲存和檢索值的出色概述。

載入必需檔案

AWS SAM 使用 esbuild 來打包你的 TypeScript 程式碼。但是,esbuild 的完整 API 並未暴露,也不支援 esbuild 外掛。這在使用 Prisma ORM 時會導致問題,因為某些檔案(如 `schema.prisma`)必須在執行時可用。

為了解決這個問題,你需要在程式碼中直接引用所需檔案以正確打包它們。在你的應用程式中,你可以在例項化 Prisma ORM 的地方新增以下幾行。

app.ts
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` 的外掛列表中

serverless.yml
plugins:
- serverless-dotenv-plugin

現在,你的 `.env` 檔案中的環境變數將在打包或部署時自動載入。

serverless package
顯示CLI結果

僅部署必需檔案

為了減小部署佔用空間,你可以更新部署過程以僅上傳應用程式所需的檔案。下面的 Serverless 配置檔案 `serverless.yml` 顯示了一個 `package` 模式,該模式僅包含與 Lambda 執行時相關的 Prisma ORM 引擎檔案,並排除了其他檔案。這意味著當 Serverless Framework 打包你的應用程式進行上傳時,它只包含一個引擎檔案。這確保了打包的歸檔檔案儘可能小。

serverless.yml
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` 引擎檔案,如下所示:

serverless.yml
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`。你需要:

  1. 使用 `copy-webpack-plugin` 複製你的 `schema.prisma`。
  2. 在你的 `serverless.yml` 中,透過 `custom > webpack > packagerOptions > scripts` 執行 `prisma generate`。
  3. 僅打包正確的 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()`,如下所示:

webpack.config.js
const nodeExternals = require('webpack-node-externals')

module.exports = {
// ... other configuration
externals: [nodeExternals()],
// ... other configuration
}

更新你的 `webpack.config.js` 檔案中的 `plugins` 屬性以包含 `copy-webpack-plugin`

webpack.config.js
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`,如下所示:

serverless.yml
custom:
webpack:
packagerOptions:
scripts:
- prisma generate

這將確保在 webpack 打包你的程式碼後,Prisma Client 根據你的 schema 生成。沒有此步驟,你的應用程式將無法執行。

最後,你將需要排除與 AWS Lambda 執行時不匹配的 Prisma ORM 查詢引擎。透過新增以下指令碼來更新你的 `serverless.yml`,該指令碼確保最終打包的歸檔檔案中僅包含所需的查詢引擎 `rhel-openssl-1.0.x`。

serverless.yml
custom:
webpack:
packagerOptions:
scripts:
- prisma generate
-- find . -name "libquery_engine-*" -not -name "libquery_engine-rhel-openssl-*" | xargs rm

如果你正在部署到ARM64 架構的 Lambda 函式,你應該將 `find` 命令更新為以下內容:

serverless.yml
custom:
webpack:
packagerOptions:
scripts:
- prisma generate
-- find . -name "libquery_engine-*" -not -name "libquery_engine-arm64-openssl-*" | xargs rm

4. 總結

現在你可以重新打包並重新部署你的應用程式了。為此,請執行 `serverless deploy`。Webpack 輸出將顯示 schema 正在透過 `copy-webpack-plugin` 移動。

serverless package
顯示CLI結果

使用 SST 部署

使用環境變數

儘管 SST 支援 `.env` 檔案,但不推薦使用它。SST 建議使用 `Config` 以安全的方式訪問這些環境變數。

此處提供的 SST 指南 是一個關於 `Config` 入門的逐步指南。假設你已經建立了一個名為 `DATABASE_URL` 的新 secret,並且已經將該 secret 繫結到你的應用程式,你可以按如下方式設定 `PrismaClient`:

prisma.ts
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
© . This site is unofficial and not affiliated with Prisma Data, Inc.