无服务器计算的发展已经远远超出了用 API Gateway 背后的 Lambda 函数取代简单的 REST API 的范围。现代无服务器架构是完全事件驱动的、异步的,并将单体分解为协调的功能工作流程。主要企业现在在 AWS Lambda、Azure Functions 和 Cloudflare Workers 上运行生产工作负载。本文探讨了超越基础知识的模式。
事件驱动架构基础
无服务器的核心是事件驱动模型:事件生产者发出事件,事件路由器传递事件,事件消费者做出反应。 AWS 提供多种路由服务 — 用于模式感知事件总线的 EventBridge、用于基于队列解耦的 SQS、用于发布/订阅消息传递的 SNS 以及用于高吞吐量流的 Kafka。
幂等性至关重要:您的函数必须安全地处理重复事件。始终实现幂等键和重复数据删除逻辑。
interface OrderEvent {
orderId: string;
idempotencyKey: string;
items: Array<{ sku: string; quantity: number }>;
}
async function handleOrder(event: OrderEvent) {
const processed = await checkIdempotency(event.idempotencyKey);
if (processed) return { status: "duplicate" };
await processOrder(event.items);
await markIdempotent(event.idempotencyKey);
return { status: "processed" };
}
死信队列 (DLQ) 捕获失败事件以供以后分析。如果没有 DLQ,有毒的消息可能会阻塞整个管道。
扇出/扇入模式
扇出将工作负载分配给并行工作人员;扇入收集结果。 S3 事件通知可以分发到多个 Lambda 函数进行图像处理 - 一个函数生成缩略图,另一个函数提取元数据,第三个函数运行 OCR。
AWS Step Functions 提供具有 Map 状态的本机扇出:
{
"Map": {
"ItemsPath": "$.files",
"MaxConcurrency": 10,
"Iterator": {
"StartAt": "ProcessFile",
"States": {
"ProcessFile": {
"Type": "Task",
"Resource": "arn:aws:lambda:process-file",
"End": true
}
}
},
"ResultPath": "$.results",
"End": true
}
}
对于扇入,DynamoDB 充当结果聚合器。每个并行工作线程将其结果写入由相关 ID 作为键控的 DynamoDB 项目。一旦计数与预期总数匹配,最终函数就会查询所有结果。
| 图案 | 使用案例 | 延迟 |
|---|---|---|
| S3 → SQS → Lambda | 图像处理管道 | 秒 |
| 步骤函数图 | 协调并行任务 | 分钟 |
| DynamoDB 流 → Lambda | 实时聚合 | 亚秒 |
分布式事务的 Saga 模式
无服务器微服务需要分布式事务协调而无需两阶段提交。 saga 模式通过编排(每个服务发布触发下一个服务的事件)或编排(中央协调器管理工作流程)来处理此问题。
AWS Step Functions 非常适合作为传奇编排器。每个步骤都是一个任务状态,并且补偿事务会在失败时撤消工作。考虑一个提供航班、酒店和汽车租赁服务的预订系统:
const sagaDefinition = {
Comment: "Travel booking saga",
StartAt: "BookFlight",
States: {
BookFlight: {
Type: "Task",
Resource: "arn:aws:lambda:book-flight",
Catch: [{ ErrorEquals: ["States.ALL"], Next: "CancelFlight" }],
Next: "BookHotel"
},
BookHotel: {
Type: "Task",
Resource: "arn:aws:lambda:book-hotel",
Catch: [{ ErrorEquals: ["States.ALL"], Next: "CancelFlight" }],
Next: "BookCar"
},
BookCar: {
Type: "Task",
Resource: "arn:aws:lambda:book-car",
Catch: [{ ErrorEquals: ["States.ALL"], Next: "CancelHotel" }],
End: true
},
CancelFlight: { Type: "Task", Resource: "arn:aws:lambda:cancel-flight", Next: "Fail" },
CancelHotel: { Type: "Task", Resource: "arn:aws:lambda:cancel-hotel", Next: "Fail" },
Fail: { Type: "Fail" }
}
};
如果租车失败,传奇会通过补偿 Lambda 回滚酒店和航班预订。 Saga 状态应该被持久化(例如,在 DynamoDB 中)以便从部分故障中恢复。
冷启动缓解
当 Lambda 启动新的执行环境时,就会发生冷启动。 Java 和 .NET 运行时的惩罚最高,而 Node.js 和 Python 的启动时间为数十毫秒。支持 VPC 的功能会增加 ENI 连接的时间。
| 运行时 | 冷启动(中值) | 冷启动(第 99 页) |
|---|---|---|
| Node.js | 45 毫秒 | 250 毫秒 |
| 蟒蛇 | 60 毫秒 | 300 毫秒 |
| Java(SnapStart) | 150 毫秒 | 500 毫秒 |
| Java(无 SnapStart) | 3,000 毫秒 | 8,000 毫秒 |
| .NET | 2,500 毫秒 | 7,000 毫秒 |
预置并发可以使指定数量的环境保持温暖,但会产生成本。 SnapStart for Java 会拍摄初始化环境的快照,从而显着减少启动时间。 “先优化然后缓解”策略效果最好:最小化部署包、明智地选择运行时以及修剪依赖项。
使用 EventBridge 的预热调度程序可以在可预测的流量模式期间使函数保持温暖:
export async function warmUp() {
const functions = [
"order-processor", "payment-handler", "notification-service"
];
for (const fn of functions) {
await lambda.invoke({
FunctionName: fn,
InvocationType: "RequestResponse",
Payload: JSON.stringify({ warmup: true })
}).promise();
}
}
无服务器中的可观察性
无服务器可观察性具有挑战性:功能是短暂的,跟踪跨越多个服务,并且日志量很大。使用 JSON 和相关 ID 进行结构化日志记录至关重要。
const logger = {
info: (msg: string, context?: object) => {
console.log(JSON.stringify({
level: "INFO",
message: msg,
requestId: context?.awsRequestId,
timestamp: new Date().toISOString(),
...context
}));
}
};
AWS X-Ray 提供分布式跟踪,OpenTelemetry 通过 Lambda Telemetry API 提供供应商中立的自动检测。 Datadog 和 Lumigo 等第三方工具添加了针对无服务器定制的仪表板和警报。
成本优化策略
Lambda 定价基于请求:您按调用和计算持续时间付费。 ARM64 (Graviton2) 函数的成本比 x86 低 20%。通过算法优化减少执行时间,直接降低成本。
对大型负载使用 S3,而不是 Lambda 调用负载(限制为 256 KB,并按请求计费)。保留并发性以控制扩展并防止失控函数导致成本飙升。
最有效的成本优化是消除不必要的调用。定期审核您的函数触发器:删除过时的事件规则,整合类似的处理程序,并使用 S3 批处理操作而不是针对每个对象的 Lambda 调用来进行大规模数据处理。
无服务器架构现已在生产环境中成熟。事件驱动设计、传奇编排、冷启动处理和可观察性是必备的。采用无服务器优先的心态,同时对容器何时仍然是正确的选择保持务实。

