無伺服器運算的發展已經遠遠超出了用 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 呼叫來進行大規模資料處理。
無伺服器架構現已在生產環境中成熟。事件驅動設計、傳奇編排、冷啟動處理和可觀察性是必備的。採用無伺服器優先的心態,同時對容器何時仍然是正確的選擇保持務實。

