题目与场景
生产方会重试,负载模式不断演进,流量也可能不均匀。网关必须校验信封、隔离租户、保留投递证据,并让消费者明确面对至少一次投递。
面试官在考察什么
- 把协议信封转化为清晰的接入与投递契约。
- 选择幂等范围、重试状态和持久化交接边界。
- 设计租户隔离、模式演进和运维证据。
作答前的澄清问题
- 每个租户需要支持的峰值每秒事件数和负载大小是多少?
- 生产方能否无限重试,是否要求按来源或主题有序?
- 哪些消费者需要至少一次投递,能否按来源加 ID 去重?
- 是否有集中式模式注册表,原始事件需要保留多久以支持重放?
30 秒回答框架
我会在认证边缘终止 TLS,校验 CloudEvents 信封和租户配额,然后先持久化原始事件再确认接收。分区队列向消费者提供至少一次投递;当生产方保证 ID 稳定时,使用租户、来源和 ID 作为去重键。消费者确认、重试计划、死信、模式版本和租户限额让丢失与重复都可观测。
分步深挖
1. 接入与校验
支持结构化或二进制 HTTP 绑定,限制大小与内容类型,并校验 specversion、type、source、id 等必填属性。先认证租户,信封无效时不进入持久化流程。保留接收字节和请求头以便审计与重放。
2. 选择持久化边界
在返回成功前,用一次持久化操作写入不可变事件记录以及 outbox 或日志偏移。仅在队列发布尚未提交时确认可能丢事件;只用数据库又可能限制高吞吐扇出。说明延迟和持久性取舍。
3. 去重但保留重试事实
使用租户范围的 (source, id) 键,保留时间覆盖生产方重试。保存负载摘要与模式版本;同一键对应不同字节时冲突并隔离。把投递尝试与逻辑事件分开,保持重试可观测。
4. 投递与重试
消费者从分区拉取,或通过带租约的推送接收。成功确认推进尝试;超时和临时错误使用带抖动的指数退避。永久失败进入租户范围的死信流,并提供受审计的重放控制。
5. 演进与运营
入口校验模式版本,无法兼容的事件进入隔离区,并支持消费者声明能力。按租户和来源统计接收、拒绝、重复、延迟、重试、死信和重放。实施配额、加密、保留与访问控制,不记录密钥或无限制负载。
高质量示范回答
“我会在边缘认证租户、校验 CloudEvents 信封、限制大小和配额,再把原始事件和请求头持久化后确认接收。分区日志提供至少一次投递。生产方保证 ID 稳定时,去重键使用租户加来源加 ID;同一键摘要变化就隔离。消费者确认推进尝试,临时错误带抖动退避,永久错误进入可重放死信流。模式版本、租户指标、保留策略和审计日志让投递语义明确。”
常见失误
- 持久化前确认 → 崩溃会丢事件 → 在选定持久化边界后确认。
- 全局按 ID 去重 → 租户或来源会冲突 → 限定键范围并校验摘要。
- 承诺恰好一次 → 重试和消费者副作用仍可能发生 → 声明至少一次并要求消费者幂等。
- 丢弃不兼容模式 → 无法调试和重放 → 隔离并保留带版本证据。
追问与回答
网关能保证有序吗?
只能在明确范围内保证,例如来源和主题分区。保留序列信息,让同一键进入同一分区,并说明重试或并行消费者可能延迟后续事件。
生产方复用 ID 但更换负载怎么办?
比较已保存摘要,冲突时拒绝或隔离。不能静默覆盖首个事件,应告警生产方,因为去重契约已被破坏。
如何支持租户级重放?
保留不可变事件记录,使用绑定授权的重放令牌、新的尝试 ID、速率限制和审计轨迹。重放仍需通过模式与去重校验,不能绕过消费者隔离。