Serverless 应用开发:AWS Lambda 与 API Gateway
什么是 Serverless 无服务器架构?
Serverless 并不是真的“没有服务器”,而是将服务器管理、容量规划和维护工作全部交给云服务商,开发者只需关注业务代码。它的核心思想是事件驱动、按需执行、自动扩缩容、按实际用量付费。AWS Lambda 是最早也最成熟的函数即服务(FaaS)产品,配合 API Gateway 可以快速构建弹性伸缩的云原生 API。
在本教程中,你将亲手创建一个基于 AWS Lambda 和 API Gateway 的无服务器后端,实现一个简单的留言板接口,并了解从开发到监控的完整流程。
前置准备
在开始之前,请确认你具备以下条件:
- 一个 AWS 账号(注册时需要信用卡,本示例使用的资源都在免费套餐范围内)
- 本地安装 AWS CLI 并完成
aws configure配置 - Node.js 16+ 运行环境
- 基础的 JavaScript 与 HTTP 协议知识
核心概念速览
-
AWS Lambda 函数
一段在托管环境中运行的代码,可以由 HTTP 请求、S3 事件、定时触发器等事件源调用。每次执行称为一次“调用”,按调用次数与运行时长计费。 -
API Gateway
完全托管的 API 管理服务,用于创建、发布、维护 RESTful API。它能将 HTTP 请求代理到 Lambda 函数,并处理身份验证、流量控制、请求/响应转换。 -
事件驱动模型
不同于传统持续运行的服务器,Serverless 函数处于休眠状态直到事件到达,然后快速启动执行,执行完毕后释放资源。
实战项目:构建 Serverless 留言板 API
我们将创建一个留言板 API,提供 GET /messages 和 POST /messages 两个端点。消息暂时存储在内存数组中(仅为演示,生产环境应使用 DynamoDB 或 RDS)。
第一步:编写 Lambda 函数代码
在本地新建项目文件夹 serverless-message-api,初始化并创建文件。
mkdir serverless-message-api && cd serverless-message-api
npm init -y
创建 index.js(AWS Lambda 的入口文件):
// 简单内存存储,重启 Lambda 后消息会丢失
let messages = [
{ id: 1, text: 'Hello Serverless!', createdAt: new Date().toISOString() }
];
exports.handler = async (event) => {
// API Gateway 会通过 event.httpMethod 传递 HTTP 方法
const { httpMethod, path, body } = event;
// GET /messages 返回消息列表
if (httpMethod === 'GET' && path === '/messages') {
return {
statusCode: 200,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(messages)
};
}
// POST /messages 添加新消息
if (httpMethod === 'POST' && path === '/messages') {
try {
const { text } = JSON.parse(body || '{}');
if (!text) {
return {
statusCode: 400,
body: JSON.stringify({ error: 'text is required' })
};
}
const newMessage = {
id: messages.length + 1,
text,
createdAt: new Date().toISOString()
};
messages.push(newMessage);
return {
statusCode: 201,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(newMessage)
};
} catch (err) {
return {
statusCode: 400,
body: JSON.stringify({ error: 'Invalid JSON body' })
};
}
}
// 未匹配的路由
return {
statusCode: 404,
body: JSON.stringify({ error: 'Not Found' })
};
};
打包函数代码为 ZIP 文件(后续部署需要):
zip -r function.zip index.js
第二步:在 AWS Lambda 控制台创建函数
- 登录 AWS 管理控制台,进入 Lambda 服务。
- 点击 创建函数,选择 从头开始撰写。
- 函数名称输入
MessageApiHandler,运行时选择 Node.js 18.x(兼容 16+)。 - 架构选择
x86_64,权限部分选择 创建一个具有基本 Lambda 权限的执行角色,AWS 会自动生成一个基础 IAM 角色。 - 点击 创建函数。
进入函数详情页后,上传代码包:
- 在“代码源”区域,点击 从 .zip 文件上传,选择刚才生成的
function.zip。 - 上传成功后,编辑器会显示
index.js内容,可以在这里直接微调。
现在你可以先测试 Lambda 本身:点击 测试,创建一个新的测试事件,模拟 API Gateway 传入的结构。例如:
{
"httpMethod": "GET",
"path": "/messages",
"body": null
}
点击测试,应该能看到返回状态码 200 和消息数组。这一步确保函数逻辑正确。
第三步:配置 API Gateway 触发器
让 Lambda 能够被外部 HTTP 请求调用,需要添加 API Gateway 触发器。
- 在 Lambda 函数页面顶部,点击 添加触发器。
- 触发器源选择 API Gateway。
- 意图选择 创建新 API,API 类型选择 REST API。
- 安全选择 打开(本教程为简单演示,生产环境应使用授权或 API 密钥)。
- 点击 添加,AWS 会自动创建 API Gateway 资源、方法和集成。
触发器创建完成后,“配置”选项卡会显示 API 端点 URL,类似:
https://abcdefghij.execute-api.us-east-1.amazonaws.com/default/MessageApiHandler
此时直接访问这个 URL,你会发现只响应根路径 / 的请求。我们还需要在实际的 API Gateway 控制台进行路由细化,让 Lambda 能感知到不同路径和方法。
第四步:细化 API Gateway 路由设置
- 在 Lambda 触发器列表中,点击刚才创建的 API 名称,进入 API Gateway 控制台。
- 左侧面板选择 资源,你会看到现有资源结构:
/下面包含一个ANY方法。我们需要创建/messages资源,并将 GET 和 POST 方法集成到同一个 Lambda。 - 选中
/根资源,点击 创建资源,资源名称messages,勾选 启用 API Gateway CORS(方便浏览器调用)。点击 创建资源。 - 选中
/messages资源,点击 创建方法,方法类型选GET,集成类型选择 Lambda 函数,勾选 使用 Lambda 代理集成,Lambda 区域选择与函数一致的区域,函数名输入MessageApiHandler。点击 创建方法。 - 同样操作,为
/messages创建POST方法,也使用相同的 Lambda 代理集成。 - 现在你可能还需要处理根路径的
ANY方法,可以删除它或者保留,建议删除以免混淆。
为了让 Lambda 正确解析路径,需要调整代理传递行为。因为使用了 Lambda 代理集成,API Gateway 会把完整的请求信息(包括 path 和 httpMethod)传给 Lambda,所以我们的函数内路由逻辑可以正常工作。
第五步:部署 API
在 API Gateway 控制台,点击 部署 API,部署阶段选择 default(如果没有,新建一个 prod 阶段)。部署后你会得到一个调用 URL:
https://abcdefghij.execute-api.us-east-1.amazonaws.com/prod
现在的完整端点变成了:
GET https://abcdefghij.execute-api.us-east-1.amazonaws.com/prod/messagesPOST https://abcdefghij.execute-api.us-east-1.amazonaws.com/prod/messages
第六步:测试 API
使用 curl 或 Postman 进行测试:
# 获取消息列表
curl https://your-api-id.execute-api.region.amazonaws.com/prod/messages
# 发送新消息
curl -X POST https://your-api-id.execute-api.region.amazonaws.com/prod/messages \
-H "Content-Type: application/json" \
-d '{"text": "Serverless 好方便!"}'
# 再次获取消息,应该看到两条记录
curl https://your-api-id.execute-api.region.amazonaws.com/prod/messages
响应示例:
[
{ "id": 1, "text": "Hello Serverless!", "createdAt": "..." },
{ "id": 2, "text": "Serverless 好方便!", "createdAt": "..." }
]
第七步:监控与日志
每次 Lambda 执行都会自动记录日志到 Amazon CloudWatch Logs。
- 在 Lambda 函数控制台,点击 监控 选项卡,可以看到调用次数、错误数、持续时间等指标。
- 点击 查看 CloudWatch 日志,可以进入日志组,查看每次请求的详细日志。如果集成出现问题,这里的日志是最重要的排错依据。
你可以在 Lambda 代码中添加 console.log 来输出调试信息,它们会出现在 CloudWatch Logs 中。
进阶优化与实践建议
使用环境变量
不要把数据库连接串或密钥硬编码。在 Lambda 配置页面的 环境变量 中可以添加键值对,代码内通过 process.env.KEY_NAME 访问。
持久化存储
本示例使用内存数组,函数冷启动后数据会丢失。实际项目中,消息应保存到 Amazon DynamoDB(无服务器数据库)或 RDS。Lambda 有与 DynamoDB 的原生集成,可以通过 SDK 直接操作。
冷启动优化
Lambda 在闲置后会被回收,再次唤醒时有冷启动延迟。减少冷启动影响的方法:
- 使用较小的部署包(< 50 MB)。
- 选择
nodejs运行时初始化较快的语言。 - 避免在全局作用域执行耗时操作(如网络请求),放到 handler 内部。
- 对于延迟敏感的应用,可配置 预置并发(Provisioned Concurrency,额外付费)。
错误处理与重试
Lambda 默认会重试异步调用(如 S3 触发),API Gateway 调用的同步请求不会自动重试。你的代码应恰当返回错误状态码,让客户端决定重试策略。可以配置 API Gateway 的 网关响应 自定义错误消息格式。
API 网关的更多能力
- 自定义域名:在 API Gateway 中设置自定义域名并关联 SSL 证书。
- 请求验证:为 POST 方法配置模型和验证,阻止无效请求进入 Lambda。
- 使用阶段变量:在不同部署阶段(dev, prod)使用不同的 Lambda 版本或别名。
清理资源
为避免产生意外费用,测试完成后请删除相关资源:
- 删除 Lambda 函数。
- 删除 API Gateway 中的 API(在 API 列表选择删除)。
- 如果创建了 IAM 角色,可在 IAM 控制台删除对应角色。
总结
本教程从零开始搭建了一个完整的无服务器 API,覆盖了 Lambda 函数编写、API Gateway 集成、路由配置、部署与测试。你学会了 Serverless 架构的基本范式:用函数响应事件,用网关暴露服务,一切托管、按需付费。
这一模式极大降低了 Web 应用和后端服务的构建门槛,特别适合微服务、移动后端、IoT 数据处理等场景。下一步,你可以继续探索如何集成 DynamoDB、使用 SAM 模板进行 IaC 部署,或学习 AWS CDK 以编程方式管理云资源。