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)特性(例如 exportimport),因此需要创建一个 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
}

以下是一些关键点:

  1. 我们在 handler() 函数外部连接到数据库。这种做法可以复用同一个连接处理所有 HTTP 请求。如果在 handler() 函数中进行连接,每次请求都会创建一个新的连接,这会导致效率低下。
  2. 我们正在查询一个名为 records 的表。这个表目前还不存在,我们将在下面创建它。
  3. 不要将数据库凭证直接存储在代码中。我们会使用环境变量来保存这些信息。

接下来,我们更新代码以使用环境变量。同时,为了展示功能,我们也将在代码中动态创建 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_USERNAMEDATABASE_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

每个阶段(devprod)会在 AWS 上生成完全独立的基础架构,并分别使用自己的 PlanetScale 分支。
这种设置使得我们能够轻松地测试代码修改和数据库模式变化,并在与生产环境相同且完全隔离的开发环境中完成这些测试。一旦通过验证,数据库模式更改可以通过 PlanetScale 的部署请求应用到生产分支,而代码更改可以通过 serverless deploy 命令部署到生产环境。


下一步

在这篇文章中,我们学习了如何将 PlanetScale 集成到使用 Serverless Framework 在 AWS 上构建的 Node 应用程序中。这样我们拥有了一个完全 serverless 的技术栈,这种技术栈具有极高的可扩展性,同时简单易于设置和维护。
现在我们已经运行了一个基本的应用,接下来可以探索更复杂的主题,比如:

  • 创建多个 HTTP 路由
  • 为 Node 应用程序设置完整的部署工作流
  • 深入了解 PlanetScale 的数据库分支工作流、无阻塞模式更改等功能


在 AWS 上将 PlanetScale 与 Serverless Framework 的 Node 应用程序集成插图

关注公众号:程序新视界,一个让你软实力、硬技术同步提升的平台

除非注明,否则均为程序新视界原创文章,转载必须以链接形式标明本文链接

本文链接:https://choupangxia.com/2025/09/13/aws-planetscale-serverless-framework-node/