代表性面试主题

系统设计面试:设计一个有韧性的首屏聚合 API

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

题干

客户端首屏需要用户资料、权限和个性化信息流。请在每秒 2000 次请求、p95 预算 300 毫秒下设计一个 bootstrap API,覆盖部分响应、依赖故障、重试和可观测性。

题干与适用场景

bootstrap 接口编排三个下游调用。资料和权限是正确渲染外壳所必需的,信息流可以陈旧或缺失。接口必须返回带类型的响应,让客户端分别渲染安全的区块。p95 预算 300 毫秒包含编排开销,并且要说明哪些数据可以缓存、缓存多久。

面试官考察点

  • 从用户需求推导并行度、超时预算和失败语义。
  • 区分缺失数据、空结果和依赖错误。
  • 组合重试、熔断、舱壁和缓存策略,避免放大负载。
  • 设计可演进响应契约与有用的运行信号。

回答前需要澄清的问题

确认权限是否允许陈旧、信息流的新鲜度上限、客户端是否支持渐进渲染,以及调用是否共享租户和授权上下文。权限不能陈旧时必须留在关键路径;信息流若允许五分钟陈旧,可以用 stale-while-revalidate 缓存保护延迟。

30 秒回答框架

网关先完成一次认证,并行调用资料、权限和信息流,然后为组装预留截止时间。必需区块失败时拒绝或返回安全状态;可选区块返回带原因码和数据时间的明确不可用状态。重试仅用于瞬时且幂等的读取,并消耗共享预算。每个依赖设置超时、舱壁、熔断和陈旧缓存,避免一次故障让外壳空白。指标记录区块成功率、截止时间耗尽、陈旧响应和依赖饱和。

分步骤深入解答

1. 设置时间和并发预算

每秒 2000 次请求下,三个串行调用会耗尽 300 毫秒预算。并行调用,为每个依赖设置低于总截止时间的局部截止时间,并在剩余时间内完成组装与序列化。限制连接池,使用每请求取消信号,让超时依赖停止继续消耗资源。

2. 定义部分响应语义

返回稳定外壳,为每个区块标记 readystaleunavailable,并附机器可读原因和数据时间,但不泄露内部主机名。资料或权限错误应拒绝或返回登录/操作状态;信息流超时可以保留可用外壳。遵循 RFC 9457 的错误对象可以描述请求级错误,同时不假装所有区块都失败。

3. 保护依赖免受重试和故障影响

只重试瞬时错误、幂等读取,并且只能在共享截止时间内重试一次。加入抖动,熔断打开后停止重试。每个依赖的舱壁限制并发;陈旧缓存或有界默认值处理可选信息流。熔断器能防止反复故障耗尽网关容量,但不能替代超时和恢复探测。

4. 演进并观测契约

以追加字段的方式版本化,让客户端忽略未知区块,并携带请求关联标识。记录依赖延迟、超时原因、熔断状态、缓存年龄、区块状态和响应大小。为扇出树建立追踪,采样慢请求,并监控必需区块失败率、陈旧时间和重试量。契约测试覆盖权限就绪、资料陈旧、信息流不可用等混合结果。

高质量示范回答

我会先确认新鲜度和是否允许渐进渲染。网关完成一次认证,调用三个读取服务,并在总预算 300 毫秒内分配局部截止时间。响应按区块返回 readystaleunavailable。身份和权限失败时拒绝,信息流可使用有界陈旧缓存。瞬时幂等读取只允许一次带抖动的重试,并由依赖舱壁和熔断保护。指标和追踪暴露区块失败与截止时间压力,追加字段保证旧客户端继续工作。

常见错误

  • 串行调用依赖 → 延迟相加超过预算 → 有界并行并设置截止时间。
  • 用含糊的 null 返回 HTTP 200 → 客户端无法区分空数据和失败 → 使用明确区块状态和原因码。
  • 每层都重试所有错误 → 故障变成重试风暴 → 分类错误并执行共享重试预算。
  • 没有策略就缓存权限 → 授权可能过期仍被使用 → 定义新鲜度上限或失败关闭。
  • 使用一个全局熔断器 → 信息流故障阻塞身份数据 → 按依赖隔离熔断和舱壁。
  • 只记录总延迟 → 无法区分可选与必需失败 → 输出区块指标和追踪。

追问及应对

信息流很慢,但用户要立即看到外壳,怎么办?

缩短信息流截止时间,在允许的年龄内返回有界陈旧结果,否则返回 unavailable。外壳保持独立,客户端之后再加载信息流。

某区域权限数据陈旧,可以返回吗?

只有授权策略明确允许该陈旧程度,且响应传达数据年龄时才可以。敏感操作应重新向权威来源检查,不确定时失败关闭。

如何防止重试延长到 300 毫秒之后?

通过扇出上下文传递一个绝对截止时间。每次重试前预留尝试与组装时间;没有剩余时间就返回区块超时状态,不启动注定无法完成的工作。

熔断打开后依赖恢复,如何恢复流量?

冷却后发送少量半开探测。只有探测满足相同超时和错误标准才关闭熔断,否则保持打开并暴露下次探测时间。

公开来源

同类题目

相关面试工具

用 Solve 整理系统设计回答

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

查看工具