在 AWS 上将 PlanetScale 与 Serverless Framework 的 Node 应用程序集成
Serverless Framework 是一个非常适合在 AWS Lambda 上构建 Node 应用程序的工具。唯一缺少的就是一个 serverless 数据库。在本文中,我们将探索如何将 PlanetScale 用作 serverless Node 应用程序的数据库。
前提条件
在部署到 AWS Lambda 之前,你需要具备以下条件:
- 一个 AWS 账户(创建账户请访问 aws.amazon.com 并点击“Sign up”)。
- 安装在你电脑上的 serverless CLI。
注意事项
本文中的示例应该可以保持在 AWS 免费使用额度之内(每月最多享受 100 万次免费 AWS Lambda 调用),但请注意,使用 AWS 可能会产生额外的费用。
可以通过 NPM 安装 serverless CLI:
npm install -g serverless
如果你没有 NPM,或者想了解更多信息,可以阅读 Serverless 文档。
现在,通过 AWS 访问密钥将 serverless CLI 连接到你的 AWS 账户。按照 此指南 创建 AWS 访问密钥,然后在你的电脑上使用以下命令设置密钥:
serverless config credentials --provider aws --key <key> --secret <secret>
创建一个新的 serverless Node 应用程序
Serverless Framework 是一个 CLI 工具,可以帮助我们创建和部署 serverless 应用程序。它的配置存储在 serverless.yml
文件中,该文件描述了将被部署到 AWS 上的内容。
为了部署一个 Node 应用,我们可以创建一个简单的 serverless.yml
配置文件:
service: demo # 应用程序的名称 provider: name: aws runtime: nodejs18.x region: us-east-1 functions: api: handler: index.handler url: true
在上述的配置文件中,我们定义了一个名为 api
的 AWS Lambda 函数,该函数运行在 NodeJS 18 环境中,并提供了一个公开的 URL。
我们的 API 处理器(handler)将由 index.js
返回的 handler()
函数(有关处理器的更多信息,请参阅 AWS Lambda 文档)。让我们创建一个简单的 index.js
文件:
export async function handler(event) { return { hello: 'world' } }
注意,我们将使用 ESM(ECMAScript Modules)特性(例如 export
和 import
),因此需要创建一个 package.json
文件并设置 "type": "module"
:
{ "type": "module" }
我们的简单 Node 示例已经可以使用 serverless deploy
命令部署了,但在此之前,让我们先集成 PlanetScale!
连接到 PlanetScale
在你的 PlanetScale 账户中,首先创建一个数据库,该数据库的区域需要与 AWS 应用程序保持一致(本文示例是 us-east-1
)。然后,点击“Connect”按钮并选择“Connect with: @planetscale/database”。这样我们就可以检索到数据库的用户名和密码。
在代码中连接到数据库时,我们将使用 PlanetScale 的 serverless 驱动。先通过 NPM 安装该驱动:
npm install @planetscale/database
驱动安装完成后,我们可以使用 connect()
函数连接到 PlanetScale 数据库:
import { connect } from '@planetscale/database' const conn = connect({ // 使用 serverless 驱动时,主机总是 'aws.connect.psdb.cloud' host: 'aws.connect.psdb.cloud', username: '<user>', password: '<password>' }) export async function handler(event) { const result = await conn.execute('SELECT * FROM records') return result.rows }
以下是一些关键点:
- 我们在
handler()
函数外部连接到数据库。这种做法可以复用同一个连接处理所有 HTTP 请求。如果在handler()
函数中进行连接,每次请求都会创建一个新的连接,这会导致效率低下。 - 我们正在查询一个名为
records
的表。这个表目前还不存在,我们将在下面创建它。 - 不要将数据库凭证直接存储在代码中。我们会使用环境变量来保存这些信息。
接下来,我们更新代码以使用环境变量。同时,为了展示功能,我们也将在代码中动态创建 records
表:
import { connect } from '@planetscale/database' const conn = connect({ host: 'aws.connect.psdb.cloud', username: process.env.DATABASE_USERNAME, password: process.env.DATABASE_PASSWORD }) // 如果表不存在则创建该表(仅用于演示) // 在真实的应用中,我们会在函数外部运行数据库迁移操作 await conn.execute('CREATE TABLE IF NOT EXISTS records (id INT PRIMARY KEY auto_increment, name VARCHAR(255))') export async function handler(event) { // 插入一条新记录 const queryParameter = event.queryStringParameters?.name ?? 'test' await conn.execute('INSERT INTO records (name) VALUES (?)', [queryParameter]) // 查询所有记录 const result = await conn.execute('SELECT * FROM records') return result.rows }
我们现在需要设置 DATABASE_USERNAME
和 DATABASE_PASSWORD
环境变量。可以在 serverless.yml
文件中定义它们,并使用 AWS SSM(系统管理器)来安全地存储数据库密码:
provider: name: aws runtime: nodejs18.x region: us-east-1 environment: DATABASE_USERNAME: <username-here> DATABASE_PASSWORD: ${ssm:/planetscale/db-password}
数据库密码将存储在 AWS SSM 中(不会额外收费),所以它不会直接暴露在代码中。DATABASE_PASSWORD
将通过 ${ssm:/planetscale/db-password}
在部署时从 SSM 中检索值。可以通过以下 AWS CLI 命令创建 SSM 参数:
aws ssm put-parameter --region us-east-1 --name '/planetscale/db-password' --type SecureString --value 'replace-me' # 将 `replace-me` 替换为你的实际数据库密码!
如果你不使用 AWS CLI,也可以通过 AWS Console 创建参数:
创建 SSM 参数示例。
以上,我们的应用程序现在已经准备好了!使用以下命令部署它:
serverless deploy
部署完成后,deploy
命令会显示我们 Node 应用程序的 URL,URL 大概是这样的:https://<id>.lambda-url.us-east-1.on.aws/
。我们可以用浏览器打开它,也可以使用 curl
发送请求:
curl https://<id>.lambda-url.us-east-1.on.aws/
响应内容应列出 records
表中的记录。每次请求该 URL 时,都会创建一条新的记录。此外,我们还可以通过提供 name
参数来改变插入数据库中的记录名称:
curl https://<id>.lambda-url.us-east-1.on.aws/?name=hello
阶段参数(Stage Parameters)
除了 AWS Lambda 和 PlanetScale 组合提供的出色扩展性之外,这种设置的另一个好处是可以结合 Serverless Framework 的阶段(stages)和 PlanetScale 的分支(branches)。
例如,我们可以设置开发(dev
)阶段用于开发环境,生产(prod
)阶段用于生产环境。dev
阶段可以使用 PlanetScale 中的开发分支,而 prod
阶段可以使用主要生产分支。
使用阶段参数,我们可以根据阶段设置不同的连接凭据:
provider: name: aws runtime: nodejs18.x region: us-east-1 environment: DATABASE_USERNAME: ${param:dbUser} DATABASE_PASSWORD: ${param:dbPassword} params: dev: dbUser: <dev-username-here> dbPassword: ${ssm:/planetscale/dev/db-password} prod: dbUser: <prod-username-here> dbPassword: ${ssm:/planetscale/prod/db-password}
部署时可以使用 --stage
选项指定阶段:
serverless deploy --stage dev serverless deploy --stage prod
每个阶段(dev
和 prod
)会在 AWS 上生成完全独立的基础架构,并分别使用自己的 PlanetScale 分支。
这种设置使得我们能够轻松地测试代码修改和数据库模式变化,并在与生产环境相同且完全隔离的开发环境中完成这些测试。一旦通过验证,数据库模式更改可以通过 PlanetScale 的部署请求应用到生产分支,而代码更改可以通过 serverless deploy
命令部署到生产环境。
下一步
在这篇文章中,我们学习了如何将 PlanetScale 集成到使用 Serverless Framework 在 AWS 上构建的 Node 应用程序中。这样我们拥有了一个完全 serverless 的技术栈,这种技术栈具有极高的可扩展性,同时简单易于设置和维护。
现在我们已经运行了一个基本的应用,接下来可以探索更复杂的主题,比如:
- 创建多个 HTTP 路由
- 为 Node 应用程序设置完整的部署工作流
- 深入了解 PlanetScale 的数据库分支工作流、无阻塞模式更改等功能
关注公众号:程序新视界,一个让你软实力、硬技术同步提升的平台
除非注明,否则均为程序新视界原创文章,转载必须以链接形式标明本文链接
本文链接:http://folen.top/2025/09/13/aws-planetscale-serverless-framework-node/