微服务稳定性治理面试题:超时、重试、隔离、熔断与过载保护
本页只放标准回答和精确原理入口,完整事故链、Demo与Runbook见稳定性治理主线。
高频问题
| 问题 | 标准回答 | 原理页 |
|---|---|---|
| 微服务雪崩怎样发生 | 下游变慢后在途请求增加,线程、连接和队列被占满;超时过长和多层重试继续放大流量,上游健康检查也被拖慢,流量转移又冲击剩余实例。 | 事故链 |
| 限流、熔断、降级区别 | 限流按容量拒绝超额请求;熔断根据下游失败或慢调用暂时阻断;降级决定失败时业务返回什么。 | 保护器分工 |
| 为什么QPS不高线程池也会满 | Little定律近似为在途数=QPS×停留时间。20QPS、5秒平均耗时就是约100并发。 | 容量模型 |
| 端到端Deadline怎样设计 | 从入口SLO扣除已耗时,为本地、下游、数据库和响应返回分配预算;每层传播剩余时间,不能每层重新给完整超时。 | Deadline |
| 分层超时应该怎样配置 | 入口总Deadline最大,Gateway、服务本地、下游逻辑调用、单次Attempt、连接池等待和DB查询都要逐层扣减,并预留响应返回时间。不能每层都配置同一个5秒,否则上游放弃后下游仍排队执行。 | 分层超时 |
| 超时能证明下游失败吗 | 不能。连接池等待超时通常请求还没发出,Connect Timeout通常没建立连接,但Read Timeout、TimeLimiter超时或Gateway 504时,下游可能已经提交事务。写请求必须进入UNKNOWN状态,通过幂等键、结果查询、对账或补偿收敛。 | 超时与取消边界 |
| 接口超时怎么定位卡在哪一层 | 先拿traceId和时间线,看请求是否到Gateway、应用、Feign/RPC、LoadBalancer目标实例和下游;再结合线程栈、HTTP连接池active/idle/pending、下游访问日志、DB慢日志、GC和熔断限流指标判断是等连接、建连、socket read、下游执行还是本地拦截。 | 超时Runbook |
| 重试预算是什么 | 除单请求次数外,限制一段时间内额外Attempt占原始请求的比例;故障扩大时预算耗尽并快速失败,避免重试风暴。 | 重试预算 |
| 为什么只能有一个主要重试层 | Gateway、Mesh、Feign、HTTP Client和业务代码都重试会乘法放大物理Attempt。应明确重试Owner,其他层关闭或只保留连接前失败重试,并共享同一Deadline和Retry Budget。 | 重试所有权 |
| 为什么指数退避还要抖动 | 没有随机抖动时大量客户端在相同时间点一起重试,形成同步波峰和惊群。指数退避拉开尝试间隔,抖动打散重试时刻,但仍必须受最大Attempt、总Deadline和预算限制。 | 退避和抖动 |
| 重试和幂等是什么关系 | 没有幂等的重试是在赌下游没执行。订单、库存、支付、短信等写操作必须携带业务幂等键,下游用唯一约束和事务保存幂等记录与业务结果;超时后按幂等键查状态,不能换新请求号重做。 | 重试与幂等 |
| Bulkhead是什么 | 把不同依赖或业务的线程、许可、连接和队列隔离,一个依赖慢时不能耗尽全部共享资源。 | 舱壁隔离 |
| 线程池隔离与信号量隔离区别 | 线程池隔离故障域更强但有切换和队列成本;信号量只限制并发、仍占调用线程,适合快速或异步调用。 | 隔离方式 |
| 队列为什么必须有界 | 无界队列把拒绝变成长时间排队,过期请求出队后仍攻击下游,并可能OOM。 | 有界队列 |
| 熔断器三个状态是什么 | CLOSED正常统计;超过最小样本和失败/慢调用阈值后OPEN快速拒绝;等待后HALF_OPEN只放少量探测,成功恢复,失败重新OPEN。 | 状态机 |
| 为什么熔断要统计慢调用 | 请求最终成功但都耗时10秒,异常率仍为0,却足以占满线程和连接。 | 慢调用熔断 |
| 熔断滑动窗口统计什么 | 通常统计最近计数窗口或时间窗口内的总调用数、失败数、失败率、慢调用数和慢调用比例;必须达到最小样本数才判断,否则低QPS接口容易误开。时间窗口更贴近实时,计数窗口样本更稳定,阈值要基于接口SLO和历史P95/P99。 | 熔断窗口指标、滑动窗口Demo |
| HALF_OPEN为什么不能全量放行 | 下游刚恢复时容量未稳定,全量积压会形成恢复风暴,应限制探测并发并逐步放量。 | 恢复 |
| HALF_OPEN探测应该怎么设计 | OPEN等待窗口到期后只放少量低风险探测请求,探测成功且RT健康再逐步恢复;失败立即回到OPEN。多个调用方要加抖动和分批恢复,避免同一时刻一起探测把下游再次打崩。 | HALF_OPEN探测 |
| Load Shedding是什么 | 系统过载时在昂贵操作前按优先级主动丢弃部分工作,保护核心请求获得可接受延迟。 | 过载保护 |
| 为什么过期请求不应该继续执行 | 如果请求在队列里等到Deadline耗尽,出队后再访问数据库或下游已经无法给用户返回价值,只会消耗线程、连接和锁,形成幽灵流量。执行前应检查剩余Deadline,不足就快速丢弃或返回超时。 | 基于Deadline的丢弃 |
| Load Shedding怎样按优先级做 | 支付确认、库存释放、幂等结果查询等核心请求要保留预算;推荐、报表、批处理等低价值任务在过载时更早拒绝、限速或暂停。同时按租户和接口拆预算,避免大租户或低价值洪峰饿死核心链路。 | 优先级和公平性、接纳控制Demo |
| 自适应并发怎样工作 | 观察低排队延迟基线和当前延迟,排队增加时降低in-flight上限,稳定后小步探索增加,并用平滑和边界防振荡。 | 自适应并发 |
| 降级为什么不能直接返回null | null无法区分真实无数据和系统故障;降级结果应包含状态、来源、版本或新鲜度,并符合业务安全边界。 | 降级 |
| SLI、SLO、SLA区别 | SLI是测量值,SLO是内部可靠性目标,SLA是可能带商业责任的外部承诺;错误预算表示允许不满足SLO的空间。 | SLO |
| 混沌工程是什么 | 先提出可证伪假设和稳态指标,在有限爆炸半径内注入故障,验证保护和恢复,再修复缺口复演,不是随机断生产。 | 故障演练 |
| Boot 2与Boot 3稳定性原理不同吗 | 原理不变;差异是Resilience4j/Sentinel兼容版本、Jakarta、自动配置和Micrometer观测。Hystrix存量用于理解和迁移,不是新项目首选。 | 技术基线 |
场景题:下游从50ms变5秒怎么办
先用入口并发限制和Load Shedding降低新流量,确认独立线程池、连接池和有界队列保护上游;Deadline必须小于入口剩余预算。熔断器同时统计慢调用,达到最小样本后OPEN。只对幂等且明确可重试错误使用全局预算和抖动。业务返回可识别降级,不伪造成功。恢复时HALF_OPEN小流量探测、实例Warmup并限制积压回放。
场景题:加了熔断为什么仍雪崩
检查熔断点是否位于昂贵操作之后、重试是否在熔断器外层、不同调用是否仍共用线程池或连接池、降级逻辑是否再次调用故障依赖,以及其他实例和异步任务是否仍施压。熔断只阻断一条调用路径,不能替代容量限制和资源隔离。
项目回答模板
我们从入口SLO建立Deadline并逐层传播剩余预算;第三方医院接口使用独立线程池、连接池和并发许可。重试集中在客户端一层,只对幂等查询和连接前失败重试一次,并受全局预算控制。熔断同时统计失败率和慢调用,HALF_OPEN限制探测。过载时优先拒绝低价值报表,核心患者身份和支付确认保留容量。每次发布用延迟、Reset、连接池耗尽等故障注入验证降级和恢复。
本章小结
稳定性面试应从事故传播讲到保护顺序和恢复,而不是孤立背限流、熔断、降级定义。
