DEV 轨道聚焦:在 Serverless 架构中拥抱失败的艺术 (DEV312)
Source: Dev.to
Serverless 架构承诺在分布式系统的强大力量中提供简洁性。但正如 Anahit Pogosova,AWS Data Hero 与 F‑Secure 首席云架构师,在她的 DEV312 会议中提醒我们的那样,简洁是一种幻觉。
“无服务器托管服务是抽象层次的进一步提升。
它们让底层基础设施看起来几乎是不可见的,几乎是魔法般的。
但使用无服务器服务并不是让我们神奇地瞬移到另一个现实。
我们仍然生活在同样混乱的物理世界中,伴随所有底层的复杂性。”
她的会议带领我们踏上了分布式系统隐藏陷阱的旅程,配以真实的案例故事和构建弹性的实用策略。
观看完整会议:
(在此嵌入或链接视频)
错误的安全感
无服务器抽象层会产生一种危险的幻觉。当我们挑选服务、将它们连接在一起,并看到一切“正常工作”时,可能会忘记潜伏在底层的分布式系统复杂性。正如 Anahit 所说:
“无服务器架构是一种,即使是你根本不知道存在的那台计算机出现故障,也可能导致整个架构不可用。”
这种更高层次的抽象让我们更难发现潜在问题,因为故障也被抽象掉了。但这些故障并没有消失——它们仍然嵌在底层的分布式系统中,随时可能显现。
一个真实案例
Anahit 分享了她在大规模构建近实时数据流架构的经验。整个设置看起来很简单:
- 生产者 → Amazon Kinesis Data Streams
- 消费者 → AWS Lambda(处理记录)
它运行得很完美——直到他们意识到数据在丢失,却毫不知情。
三个相互关联的问题
-
未配置的超时 – JavaScript SDK 的默认超时是 无限(在 SDK v2 中以前是两分钟)。当因网络故障导致对 Kinesis 的请求超时时,生产者会一直等待资源耗尽,导致无法处理新的进入数据。
-
未处理的部分失败 – 像
Kinesis.PutRecords这样的批量操作并非原子化。批次的一部分可能成功,而其余部分失败(例如在流量高峰期间触及分片限制)。SDK 返回成功,但检测并处理这些部分失败是你的责任。 -
默认的重试行为 – 当 Lambda 处理失败的记录时,它会无限期地重试整个批次(直到记录在 24 小时后过期)。一个“毒丸”记录会阻塞整个分片,导致数据因记录过期速度快于 Lambda 的追赶速度而出现级联丢失。
Anahit 将超时和重试称为“隐藏的超级能力”,因为它们对弹性极其有用——但如果使用不当,后果可能非常严重。
超时和重试的最佳实践
- 永远不要盲目相信默认的超时值。 对于 AWS SDK 请求,根据你的服务和延迟预期配置合适的超时。超时过长会浪费资源;超时过短会触发过早的重试,压垮下游系统。
“当你回到代码时,请检查所有通过网络发送的请求。确保你知道这些超时值是多少。确保你在对它们进行控制。” – Anahit
- 重试本质上是自私的。 实现不当的重试会把小问题放大为级联故障,导致整个系统崩溃。
“重试导致的分布式系统宕机次数,超过了所有其他原因的总和。” – Gregor Hohpe
安全重试的关键原则
- 仅对瞬时故障进行重试 – 如果重试无助(例如系统已过载或操作有副作用),则不要重试。
- 设置上限 – 当重试不再有帮助时停止,以避免级联故障。
- 使用带抖动的指数退避 – 均匀分布重试尝试,防止压垮系统。抖动为指数退避加入随机性,显著提升重试成功率。
Lambda 事件源映射 – 隐藏的组件
大多数开发者从未听说过 Lambda 的 事件源映射,但在使用 Lambda 与 Kinesis、DynamoDB Streams 或类似来源时,它至关重要。这个隐藏组件负责读取记录、批量化并调用你的 Lambda 函数。
默认情况下,如果 Lambda 处理批次失败,它会无限期重试,直至记录过期(Kinesis 为 24 + 小时)。一个坏记录会产生“毒丸”,阻塞整个分片,导致:
- 仍在付费的无效调用
- 同一数据的重复重新处理
- 重试期间分片完全阻塞
- 随着记录过期速度快于 Lambda 的追赶,出现级联数据丢失
Source: …
pire faster than Lambda can catch up
配置事件源映射
| 参数 | 用途 | 默认值 |
|---|---|---|
MaximumRetryAttempts | 限制重试次数 | -1(无限) |
MaximumRecordAge | 为记录在流中停留的最长时间设置超时 | -1(无限制) |
BisectBatchOnFunctionError | 将失败的批次拆分,以隔离出问题记录 | false |
DestinationConfig | 将失败的记录路由到 SQS 或 SNS 进行分析 | 无 |
ParallelizationFactor | 扩展处理能力(受 Lambda 并发限制的约束) | 1 |
“无论你做什么,请 不要 使用默认设置。” – Anahit
容量限制 – “无限” 可扩展性的现实
无服务器(Serverless)承诺可扩展性,但我们常把它误认为是无限可扩展。现实是:我们与所有其他用户共享资源,服务限制阻止任何单个用户垄断容量。
- Kinesis 分片 – 每个分片每秒 1 MiB 或 1,000 条记录。
- Lambda 并发 – 默认每个账户/区域 1,000 个并发执行。
如果触及这些限制,请求会被限流并失败。例如,一个拥有 100 个分片且并行因子为 10 的 Kinesis 流会消耗掉你的全部 Lambda 并发配额,可能导致同一账户中其他无关的 Lambda 函数失败。
将失败视为现实
在分布式系统中,一切都会失败——且经常如此。以这种思维方式进行设计——合理的超时、受限的重试以及审慎的配置——可以把无服务器架构从脆弱的幻象转变为坚韧、可投入生产的系统。
与时间相关的最佳实践
-
为超时做好计划 – 永远不要信任默认值。设置适合你使用场景的明确超时值。
-
实现安全的重试 – 仅对瞬时故障进行重试,强制限制,并使用带抖动的指数退避。
-
处理部分失败 – 批处理操作不是原子性的;检测并重试失败的部分。
-
了解你的服务限制 – 理解容量约束和限流行为。
-
配置事件源映射 – 不要依赖 Lambda 与 Kinesis/DynamoDB Streams 的默认设置。
-
保持偏执(以好的方式) – 正如 Martin Kleppmann 所说:
“在分布式系统中,怀疑、悲观和偏执会带来回报。”
-
Anahit 的结束建议 –
“分布式系统和架构很难,但它们可以教会我们一项宝贵的技能——拥抱真实世界的混沌。每一次失败都是改进的机会,让我们的系统变得更具弹性。”
-
Werner Vogels 博士的提醒 –
“一切都会失败,而且一直如此。”我们能做的最好的事就是保持冷静,并在这些失败发生时做好准备。
关于此帖子
此帖子是 DEV Track Spotlight 系列的一部分,旨在突出 AWS re:Invent 2025 开发者社区(DEV)轨道 中的精彩议题。
DEV 轨道概览
- 60 场独特议题
- 93 位演讲者,包括 AWS 社区成员(AWS Heroes、Community Builders、用户组领袖)以及 AWS 与 Amazon 员工
涵盖主题
| 类别 | 亮点 |
|---|---|
| 🤖 GenAI 与 Agentic AI | 多代理系统、Strands Agents SDK、Amazon Bedrock |
| 🛠️ 开发者工具 | Kiro、Kiro CLI、Amazon Q Developer、AI 驱动的开发 |
| 🔒 安全 | AI 代理安全、容器安全、自动化修复 |
| 🏗️ 基础设施 | 无服务器、容器、边缘计算、可观测性 |
| ⚡ 现代化 | 传统应用改造、CI/CD、功能标记 |
| 📊 数据 | Amazon Aurora DSQL、实时处理、向量数据库 |
本系列的每篇文章都会深入探讨一场议题,分享:
- 关键洞见
- 实用收获
- 完整录播链接
无论您是现场参加了 re:Invent,还是远程回看,这些议题都展示了我们开发者社区的最佳实践——真实代码、真实演示、真实学习。
敬请关注,我们将持续聚焦这些精彩议题,并致敬让 DEV 轨道熠熠生辉的演讲者们!