题干与适用场景
bootstrap 接口编排三个下游调用。资料和权限是正确渲染外壳所必需的,信息流可以陈旧或缺失。接口必须返回带类型的响应,让客户端分别渲染安全的区块。p95 预算 300 毫秒包含编排开销,并且要说明哪些数据可以缓存、缓存多久。
面试官考察点
- 从用户需求推导并行度、超时预算和失败语义。
- 区分缺失数据、空结果和依赖错误。
- 组合重试、熔断、舱壁和缓存策略,避免放大负载。
- 设计可演进响应契约与有用的运行信号。
回答前需要澄清的问题
确认权限是否允许陈旧、信息流的新鲜度上限、客户端是否支持渐进渲染,以及调用是否共享租户和授权上下文。权限不能陈旧时必须留在关键路径;信息流若允许五分钟陈旧,可以用 stale-while-revalidate 缓存保护延迟。
30 秒回答框架
网关先完成一次认证,并行调用资料、权限和信息流,然后为组装预留截止时间。必需区块失败时拒绝或返回安全状态;可选区块返回带原因码和数据时间的明确不可用状态。重试仅用于瞬时且幂等的读取,并消耗共享预算。每个依赖设置超时、舱壁、熔断和陈旧缓存,避免一次故障让外壳空白。指标记录区块成功率、截止时间耗尽、陈旧响应和依赖饱和。
分步骤深入解答
1. 设置时间和并发预算
每秒 2000 次请求下,三个串行调用会耗尽 300 毫秒预算。并行调用,为每个依赖设置低于总截止时间的局部截止时间,并在剩余时间内完成组装与序列化。限制连接池,使用每请求取消信号,让超时依赖停止继续消耗资源。
2. 定义部分响应语义
返回稳定外壳,为每个区块标记 ready、stale 或 unavailable,并附机器可读原因和数据时间,但不泄露内部主机名。资料或权限错误应拒绝或返回登录/操作状态;信息流超时可以保留可用外壳。遵循 RFC 9457 的错误对象可以描述请求级错误,同时不假装所有区块都失败。
3. 保护依赖免受重试和故障影响
只重试瞬时错误、幂等读取,并且只能在共享截止时间内重试一次。加入抖动,熔断打开后停止重试。每个依赖的舱壁限制并发;陈旧缓存或有界默认值处理可选信息流。熔断器能防止反复故障耗尽网关容量,但不能替代超时和恢复探测。
4. 演进并观测契约
以追加字段的方式版本化,让客户端忽略未知区块,并携带请求关联标识。记录依赖延迟、超时原因、熔断状态、缓存年龄、区块状态和响应大小。为扇出树建立追踪,采样慢请求,并监控必需区块失败率、陈旧时间和重试量。契约测试覆盖权限就绪、资料陈旧、信息流不可用等混合结果。
高质量示范回答
我会先确认新鲜度和是否允许渐进渲染。网关完成一次认证,调用三个读取服务,并在总预算 300 毫秒内分配局部截止时间。响应按区块返回 ready、stale 或 unavailable。身份和权限失败时拒绝,信息流可使用有界陈旧缓存。瞬时幂等读取只允许一次带抖动的重试,并由依赖舱壁和熔断保护。指标和追踪暴露区块失败与截止时间压力,追加字段保证旧客户端继续工作。
常见错误
- 串行调用依赖 → 延迟相加超过预算 → 有界并行并设置截止时间。
- 用含糊的 null 返回 HTTP 200 → 客户端无法区分空数据和失败 → 使用明确区块状态和原因码。
- 每层都重试所有错误 → 故障变成重试风暴 → 分类错误并执行共享重试预算。
- 没有策略就缓存权限 → 授权可能过期仍被使用 → 定义新鲜度上限或失败关闭。
- 使用一个全局熔断器 → 信息流故障阻塞身份数据 → 按依赖隔离熔断和舱壁。
- 只记录总延迟 → 无法区分可选与必需失败 → 输出区块指标和追踪。
追问及应对
信息流很慢,但用户要立即看到外壳,怎么办?
缩短信息流截止时间,在允许的年龄内返回有界陈旧结果,否则返回 unavailable。外壳保持独立,客户端之后再加载信息流。
某区域权限数据陈旧,可以返回吗?
只有授权策略明确允许该陈旧程度,且响应传达数据年龄时才可以。敏感操作应重新向权威来源检查,不确定时失败关闭。
如何防止重试延长到 300 毫秒之后?
通过扇出上下文传递一个绝对截止时间。每次重试前预留尝试与组装时间;没有剩余时间就返回区块超时状态,不启动注定无法完成的工作。
熔断打开后依赖恢复,如何恢复流量?
冷却后发送少量半开探测。只有探测满足相同超时和错误标准才关闭熔断,否则保持打开并暴露下次探测时间。