Zillow 如何在 AWS Step Functions 上运行每日 1 亿条通知

Zillow 如何在 AWS Step Functions 上运行每日 1 亿条通知

💡 原文英文,约3300词,阅读约需12分钟。
📝

内容提要

Zillow 每天发送超1亿条个性化邮件和推送通知。原架构中每个营销活动由独立微服务实现,导致重复开发、行为不一致和运维成本高。Zillow 与 AWS 合作构建配置驱动的 Campaign Orchestrator,基于 Step Functions Express Workflows 运行短时工作流,并配合可复用的 Universal Content Generator 模块,采用路由器集中控制、HTTP Invoke 直连模块、批处理优化和 JSONata 测试验证。新架构将构建时间从32周降至9周,维护时间从每周8小时降至2小时,显著提升产品迭代速度。

🔎

延伸解读

从“每活动一服务”到配置驱动的取舍

Zillow 原架构为每个营销活动单独建微服务,导致重复开发、行为不一致和运维成本高。新方案将共享逻辑抽成可复用模块,并把活动决策移入配置,由统一的 Campaign Orchestrator 调度。这种转变并非简单技术替换,而是组织协作方式的调整:产品团队通过配置和模块组合即可上线活动,无需等待中央团队。文章也指出,每个活动仍拥有独立工作流和队列,共享代码不等于共享故障,隔离性通过独立状态机和断路器实现。

Express Workflows 的适用边界

Zillow 选择 Step Functions Express Workflows 而非 Standard,核心依据是工作负载特征:每天超 1 亿次执行、单次仅数秒、峰值每秒数千次,且模块设计为幂等,因此“至少一次”执行保证足够。文章明确 Express 有五分钟执行上限,适合短时工作流;Standard 则面向持久、长时任务。这一选择提醒读者,工作流引擎选型应先明确吞吐、延迟和一致性要求,而非默认追求最强保证。

批处理降本的关键前提

批处理是 Zillow 控制成本的重要手段:将多条消息合并为一次工作流执行,可大幅减少 Express 请求数和 HTTP 调用。文章给出经验法则——批量运行时间不超过单条运行的十倍即可省钱,实际批量仅比单条慢 10% 到 20%。但批处理生效的前提是每个步骤都支持批量输入输出,且按 tracking ID 保留单条结果,以便逐条投递、重试或丢弃。若模块 API 不支持批量,则无法构建,说明批处理需在模块契约层面统一设计。

配置化工作流的验证与配额风险

配置驱动提升了迭代速度,但也把行为分散到 JSONata 表达式和活动配置中,因此 Zillow 要求共享表达式必须有单元测试,并通过 Step Functions TestState API 在真实运行时验证,失败即阻断部署。文章还强调,HTTP Invoke 并发默认配额低于 Express 启动速率,需提前按容量模型申请提额,否则吞吐会受限。这两点提示:配置化并非降低工程要求,而是把验证和容量规划前移,成为上线前的必要环节。

❓

Q&A

Zillow 原来的通知系统存在哪些问题,为什么要重构?

原系统中每个营销活动由独立微服务实现,超过 20 个邮件和推送活动由 10 多个微服务生成。每个服务都有自己的工作流、数据模型和业务规则,导致重复开发、行为不一致,并增加了发布、监控、日志、仪表盘和值班支持的运维开销。新功能需要在每个服务中重新构建和测试,拖慢了产品迭代。

Zillow 为什么选择 AWS Step Functions Express Workflows 而不是 Standard 或其他工作流引擎?

Zillow 评估了 Temporal、Flowable、自研引擎以及 Step Functions 的 Standard 和 Express 模式。Step Functions 是无服务器的,无需运维服务器或工作池,团队可以快速启动试点。Express Workflows 适合高吞吐、低延迟的短时工作流,默认启动配额更高,且工作流设计为幂等模块调用,至少一次执行保证已足够。相比自研引擎,Step Functions 的构建和维护工作量约为四分之一。

Campaign Orchestrator 的整体架构是怎样的?

Campaign Orchestrator 是一个配置驱动的编排层。入口服务将消息放入队列,路由器读取 Amazon SQS 并应用活动控制(如批处理、幂等检查、暂停/恢复、速度控制),然后为每个活动启动对应的 Step Functions Express Workflow。工作流中的每个步骤通过 HTTP Invoke 调用 Universal Content Generator (UCG) 的可复用模块,最后由投递服务发送消息。

Universal Content Generator (UCG) 是什么,它解决了什么问题?

UCG 是 Campaign Orchestrator 背后的模块化内容生成层,将原本分散在 10 多个独立生成器中的共享能力组织为可复用、无状态、模式驱动的模块。模块处理属性水合、隐藏房源过滤、通用数据加载、推荐、A/B 测试和内容组装等。集中后所有活动共享一个服务集群,负载分布更均匀,避免了某些每日活动运行 4 小时后生成器闲置 20 小时的问题。

批处理模式如何帮助 Zillow 降低成本并提升吞吐量?

路由器可以将多条消息分组,用一个工作流执行代替每条消息一个工作流。例如 100 条消息单独处理会产生 100 次工作流执行和 400 次 HTTP 请求,批处理后可减少为一次工作流和四次 HTTP 请求。Express Workflows 按请求和运行时间计费,批处理减少了请求数,且批量运行时间仅比单条长约 10% 到 20%,因此一批 10 条消息比 10 次单独运行便宜约 90%。批处理还减少了 StartExecution 速率、HTTP Invoke 并发和日志吞吐的占用。

新架构上线后取得了哪些可量化的成果?

新架构将构建时间从 32 个开发周降至 9 周,持续维护时间从每周约 8 小时降至 2 小时。系统按需扩展,从早期流量阶段到每天超过 1 亿次工作流执行。产品团队可以自助通过配置和共享模块迭代,减少跨团队依赖,显著提升了产品迭代速度。

🏷️

标签

➡️

继续阅读