代表性面试主题

系统设计面试:设计 CloudEvents 事件接入网关

系统设计困难
Offer.cc 编辑团队发布 更新

题干

设计一个多租户网关,接收 HTTP CloudEvents 并路由给内部消费者,既不丢事件,也不重复业务副作用。

题目与场景

生产方会重试,负载模式不断演进,流量也可能不均匀。网关必须校验信封、隔离租户、保留投递证据,并让消费者明确面对至少一次投递。

面试官在考察什么

  • 把协议信封转化为清晰的接入与投递契约。
  • 选择幂等范围、重试状态和持久化交接边界。
  • 设计租户隔离、模式演进和运维证据。

作答前的澄清问题

  • 每个租户需要支持的峰值每秒事件数和负载大小是多少?
  • 生产方能否无限重试,是否要求按来源或主题有序?
  • 哪些消费者需要至少一次投递,能否按来源加 ID 去重?
  • 是否有集中式模式注册表,原始事件需要保留多久以支持重放?

30 秒回答框架

我会在认证边缘终止 TLS,校验 CloudEvents 信封和租户配额,然后先持久化原始事件再确认接收。分区队列向消费者提供至少一次投递;当生产方保证 ID 稳定时,使用租户、来源和 ID 作为去重键。消费者确认、重试计划、死信、模式版本和租户限额让丢失与重复都可观测。

分步深挖

1. 接入与校验

支持结构化或二进制 HTTP 绑定,限制大小与内容类型,并校验 specversiontypesourceid 等必填属性。先认证租户,信封无效时不进入持久化流程。保留接收字节和请求头以便审计与重放。

2. 选择持久化边界

在返回成功前,用一次持久化操作写入不可变事件记录以及 outbox 或日志偏移。仅在队列发布尚未提交时确认可能丢事件;只用数据库又可能限制高吞吐扇出。说明延迟和持久性取舍。

3. 去重但保留重试事实

使用租户范围的 (source, id) 键,保留时间覆盖生产方重试。保存负载摘要与模式版本;同一键对应不同字节时冲突并隔离。把投递尝试与逻辑事件分开,保持重试可观测。

4. 投递与重试

消费者从分区拉取,或通过带租约的推送接收。成功确认推进尝试;超时和临时错误使用带抖动的指数退避。永久失败进入租户范围的死信流,并提供受审计的重放控制。

5. 演进与运营

入口校验模式版本,无法兼容的事件进入隔离区,并支持消费者声明能力。按租户和来源统计接收、拒绝、重复、延迟、重试、死信和重放。实施配额、加密、保留与访问控制,不记录密钥或无限制负载。

高质量示范回答

“我会在边缘认证租户、校验 CloudEvents 信封、限制大小和配额,再把原始事件和请求头持久化后确认接收。分区日志提供至少一次投递。生产方保证 ID 稳定时,去重键使用租户加来源加 ID;同一键摘要变化就隔离。消费者确认推进尝试,临时错误带抖动退避,永久错误进入可重放死信流。模式版本、租户指标、保留策略和审计日志让投递语义明确。”

常见失误

  • 持久化前确认 → 崩溃会丢事件 → 在选定持久化边界后确认。
  • 全局按 ID 去重 → 租户或来源会冲突 → 限定键范围并校验摘要。
  • 承诺恰好一次 → 重试和消费者副作用仍可能发生 → 声明至少一次并要求消费者幂等。
  • 丢弃不兼容模式 → 无法调试和重放 → 隔离并保留带版本证据。

追问与回答

网关能保证有序吗?

只能在明确范围内保证,例如来源和主题分区。保留序列信息,让同一键进入同一分区,并说明重试或并行消费者可能延迟后续事件。

生产方复用 ID 但更换负载怎么办?

比较已保存摘要,冲突时拒绝或隔离。不能静默覆盖首个事件,应告警生产方,因为去重契约已被破坏。

如何支持租户级重放?

保留不可变事件记录,使用绑定授权的重放令牌、新的尝试 ID、速率限制和审计轨迹。重放仍需通过模式与去重校验,不能绕过消费者隔离。

公开来源

同类题目

相关面试工具

用 Solve 整理系统设计回答

从澄清需求开始,展开规模、架构、组件选择和取舍。

查看工具