问题与范围
平台前置于多个 API 服务。流量可能在一分钟内升高 20 倍,下游数据库、搜索或第三方依赖的容量不同。请设计请求分类、准入、排队、负载削减、降级响应和恢复机制。网关不负责业务鉴权、完整 WAF 规则或替下游修复容量问题。
面试官在考察什么
核心是把“限流”与“过载保护”区分开:限流通常按身份或窗口限制速率,准入控制则依据当前并发、队列年龄和依赖健康决定是否接收工作。优秀回答会说明丢弃什么、为何丢弃、如何避免低优先级流量饿死,以及恢复时如何防止流量瞬间回灌。
回答前要澄清的问题
- 哪些请求是关键路径,哪些可以延迟、缓存或返回降级结果?
- 目标是保护网关自身、某个依赖、某个租户,还是全部边界?
- 允许排队多久?超时后客户端应重试、轮询还是接受空结果?
- 高峰时是否需要按租户、区域、API 或成本公平分配容量?
- 哪些状态码、响应头和指标对调用方可见?
30 秒回答框架
“我会在入口解析请求类、租户和成本标签,先做硬性并发与预算检查,再把可接受的工作送入按优先级和租户分区的有限队列。准入控制器根据 in-flight、队列年龄、错误率和依赖信号动态调整目标并发;超载时优先拒绝可重试或低价值工作,对关键请求保留保底容量。可缓存或可近似的操作走降级路径,拒绝响应携带明确的重试时间。恢复采用渐进放量、租约和熔断探测,避免恢复风暴。”
分步深入设计
入口先验证请求大小、超时预算和租户配额,再映射到 criticality、cost、retryability 与 dependency 标签。标签由受信任的路由配置生成,不能让客户端自报“关键”。配置版本随请求记录,便于解释一次拒绝。健康检查和管理流量使用独立保留池,避免数据流量耗尽控制面。
每个 API 和依赖维护 in-flight 上限、排队上限和超时预算。使用信号量或租约计数保护真实资源;队列必须有界,不能用无限消息积压掩盖过载。准入成功后再消耗预算,取消或超时要释放租约。对于流式请求,按连接和字节另设预算,避免一条长连接占满并发槽。
调度器按优先级、租户权重和老化时间选择工作。关键请求拥有保底并发,低优先级请求可被丢弃或转入延迟队列;老化机制防止长期饥饿。一个租户的突发不能借用其他租户的保底额度。跨区域部署时可在本地快速拒绝,避免为了全局精确计数增加故障依赖。
控制器每个短窗口更新目标并发:当 p95 延迟、队列年龄或下游错误超过阈值时降低窗口;稳定时缓慢增加。信号要做平滑和滞回,避免在阈值附近抖动。客户端重试不能被当作健康信号;记录重试放大倍数,并通过 Retry-After、随机抖动和重试预算限制回流。
负载削减策略按请求语义选择。可重复计算的推荐、统计和预览可以返回缓存或近似结果;写入、支付、权限变更等关键操作通常快速失败并要求调用方安全重试。降级结果必须带版本、时间和新鲜度,不能伪装成完整数据。网关不应在不理解业务的情况下随意丢弃不可重试副作用。
当依赖出现超时或错误,依赖隔离池限制其连接、并发和重试预算,断路器只允许受控探测。缓存和静态响应在隔离池内服务;探测成功后渐进恢复。响应统一记录准入决策、策略版本、拒绝原因、队列等待和依赖信号,避免只看到一堆 429 却不知道哪个边界耗尽。
监控准入率、按优先级和租户的拒绝率、最老队列年龄、in-flight、p95/p99 延迟、下游错误、重试放大、降级新鲜度和恢复斜率。对账资源预算与实际连接、线程、数据库连接和队列任务。故障注入覆盖突发流量、慢依赖、策略配置错误、控制器失联、区域网络分区和恢复后的重放风暴。
高质量示范回答
“我会在网关入口给请求打上受信任的关键性、成本、可重试性和依赖标签。每个 API/依赖都有有限并发、有限队列和保底容量;调度器按优先级、租户权重和老化时间取任务。控制器用 p95 延迟、队列年龄和下游错误调节目标并发,带滞回避免抖动。过载时优先拒绝低价值、可重试工作,关键写入保留额度;推荐和预览可返回带新鲜度的缓存结果。
所有拒绝响应带稳定原因、Retry-After 和请求 ID。依赖隔离池、重试预算和受控探测防止级联失败,恢复采用渐进放量。指标覆盖拒绝公平性、重试放大、降级新鲜度和恢复斜率;故障注入验证控制器失联、区域分区和重放风暴。系统的承诺是过载时保持关键路径的可预测延迟,而不是让所有请求都排队直到超时。”
常见错误
- 只加固定 QPS 限流 → 真实瓶颈可能是连接、CPU 或下游错误 → 结合并发、队列和依赖信号。
- 使用无限队列 → 延迟失控且掩盖容量不足 → 设置有界队列和明确拒绝。
- 所有请求同等优先 → 关键路径被低价值工作挤占 → 按语义保留容量并加老化。
- 客户端可自报高优先级 → 恶意调用者绕过保护 → 由受信任路由配置分类。
- 过载时无限重试 → 重试放大让依赖更快崩溃 → 预算、抖动和
Retry-After。 - 降级返回无时间信息的数据 → 用户误把旧结果当事实 → 标记版本、新鲜度和来源。
- 恢复立即放开全部流量 → 重放风暴再次压垮系统 → 渐进放量和受控探测。
- 跨区域追求精确全局计数 → 保护路径依赖更多故障组件 → 本地快速决策并接受有界误差。
追问与回答
追问一:准入控制和限流有什么不同?
限流通常约束某个身份在时间窗口内的请求数;准入控制决定当前工作是否能占用真实资源,考虑并发、队列等待、成本和依赖健康。两者可以同时存在,但固定 QPS 不能替代资源准入。
追问二:如何避免关键租户被低优先级租户挤出?
为关键租户保留独立并发池或保底配额,再在共享容量内按权重调度。每个租户还要有最大预算,防止其流量无限借用保留池。
追问三:为什么不让请求一直排队?
等待时间超过业务截止时间后,排队只会制造超时和重试。有限队列让系统明确拒绝过量工作,把容量和反馈交给调用方处理。
追问四:控制器使用哪些信号?
至少包括 p95/p99 延迟、in-flight、最老队列年龄、依赖错误率和资源利用率。信号需平滑、带滞回,并区分客户端重试造成的流量,避免把自我放大误判成健康。
追问五:关键写入是否可以降级?
只有业务明确允许时才可以,例如写入持久队列后异步完成。支付、权限和库存等副作用不能返回假成功;应快速失败并使用幂等键安全重试。
追问六:如何验证恢复不会再次过载?
注入依赖恢复、积压任务和客户端重试,观察渐进放量、保底容量、队列年龄和错误率。恢复控制器必须有最大增幅、冷却窗口和人工暂停开关。