韧性、可测性与部署

共 21 题
📑 题目列表 21 题
#
★★★

1. 熔断器的状态机中 Closed/Open/Half-Open 的转换条件,与超时、重试的组合策略?

请说明熔断器的状态机(Closed/Open/Half-Open)的转换条件,以及与超时、重试的组合策略?

  • 熔断器三状态转换
  • 滑动窗口与阈值
  • 与超时、重试的组合

熔断器(Circuit Breaker)用状态机保护下游依赖:Closed(关闭)——正常状态,请求正常放行,统计失败率;当失败率超过阈值(如 50% 且达到最小请求数)或连续失败达到阈值,进入 Open(打开)——熔断打开,直接快速失败(不调用下游),返回降级/错误,同时启动冷却时间(cooldown);冷却结束后进入 Half-Open(半开)——允许少量探测请求(如 1 个)试探下游,若探测成功则恢复到 Closed(关闭,重置计数),若失败则回到 Open(重新熔断,重置冷却)。转换条件:Closed→Open 由失败率/失败次数阈值触发;Open→Half-Open 由冷却时间触发;Half-Open→Closed 由探测成功触发;Half-Open→Open 由探测失败触发。与超时、重试组合:熔断是"快速失败"手段,超时是"等待上限",重试是"重试可能成功"。策略:超时限制单次等待,重试在重试窗口内做有限次重试(指数退避+抖动),熔断在整体失败率高时停止放行避免级联;熔断打开时不应重试(会再次触发),恢复后重试;熔断与重试需合理配置避免"重试放大熔断"。

熔断器是"断路器"语义:失败率触顶就断开,冷却后试探恢复。状态机由失败阈值、冷却时间、探测结果驱动。与超时、重试组合时,超时管单次、重试管次数、熔断管整体,三者配合实现快速失败与防雪崩。

#
★★★

2. 重试与超时的组合中指数退避+抖动如何避免重试风暴?

请说明重试与超时的组合,以及指数退避 + 抖动(jitter)如何避免重试风暴?

  • 指数退避
  • 抖动(jitter)
  • 重试风暴防护

重试与超时组合:超时定义单次调用等待上限,重试定义总尝试次数与退避间隔。指数退避(exponential backoff):每次重试间隔按指数增长(如 1s、2s、4s、8s…),避免短时间内高频重试给下游造成压力。抖动(jitter):在退避间隔上加入随机量(如 [0, backoff] 之间的随机值),使不同客户端/请求的重试时间错开,避免所有客户端在同一时刻同时重试形成"重试风暴"(thundering herd)。低成本抖动(full jitter)是 sleep(random(0, backoff)),均匀抖动是 sleep(backoff/2 + random(0, backoff/2))。重试风暴防护:设置最大重试次数、使用指数退避 + 抖动、限制并发重试、配合熔断(失败率高时停止重试)、传播超时预算(deadline,重试不超预算)。若不用抖动,所有失败请求会同时退避到同一时刻重试,放大下游压力造成雪崩。

指数退避让重试间隔递增,抖动让重试时刻错开,二者结合避免"重试风暴"。重试风暴是分布式系统级联故障的常见成因,需配合最大重试次数、熔断与超时预算共同防护。

public long nextBackoff(int attempt, long baseMillis) {
    long exp = Math.min(baseMillis << attempt, MAX_BACKOFF); // 指数增长
    return ThreadLocalRandom.current().nextLong(exp);         // full jitter
}
#
★★★

3. 发布策略中金丝雀、蓝绿与滚动发布的流量切换与回滚方式,各自对版本兼容的要求

请说明金丝雀(Canary)、蓝绿(Blue/Green)与滚动(Rolling)发布策略的流量切换与回滚方式,以及各自对版本兼容的要求?

  • 三种发布策略原理
  • 流量切换与回滚
  • 版本兼容要求

发布策略用于"新版本上线"的平滑切换与回滚:

  • 滚动发布(Rolling):一批一批地替换旧实例为新实例(如 K8s 滚动更新),新旧版本同时存在一段时间。流量逐步切到新版本,回滚通过逐步回退到旧版本完成。兼容要求:新老版本必须兼容(因为同一时刻新旧实例并存,需兼容数据库 schema、接口、依赖)。
  • 蓝绿发布(Blue/Green):两套环境(蓝=旧、绿=新),新版本在绿环境完全部署并验证后,通过切换负载/路由一次性把流量切到绿,旧版本(蓝)保留随时回滚。回滚是"切回蓝",快速安全。兼容要求:只需保证切换点兼容(数据库 schema 需兼容两套,因为切换瞬间新版本要读写同一数据),对应用级新旧并存要求低。
  • 金丝雀发布(Canary):先让新版本只接一小部分流量(如 5%),观察指标后逐步放大比例,直到全量。回滚是"降低/归零金丝雀流量"。兼容要求:新旧版本并存期较长,需要严格的新老版本兼容(schema、接口、依赖)。
  • 三者对比:蓝绿切换快、回滚快但成本高(双倍资源);滚动成本低但兼容要求高、回滚慢;金丝雀最安全、可灰度验证,但切换慢、兼容要求高。实际常组合(金丝雀放大后滚动/蓝绿)。

三种策略的核心差异是"流量切换粒度"与"新旧并存时间":蓝绿一次性切换(双环境)、滚动渐进切换(并旧)、金丝雀按比例灰度(先小后大)。兼容要求由"新旧并存期间是否同时读写同一数据/接口"决定。

#
★★★

4. 契约测试中消费者驱动契约如何让服务间接口变更在 CI 阶段暴露,与端到端测试的分工

请说明契约测试(Contract Testing),消费者驱动契约(Consumer-Driven Contract)如何让服务间接口变更在 CI 阶段暴露,以及与端到端测试的分工?

  • 消费者驱动契约
  • CI 阶段暴露接口变更
  • 与端到端测试的分工

契约测试验证"服务提供方接口与消费方预期是否一致",不依赖真实服务,而是针对契约(契约 = 请求/响应格式、字段、状态)进行验证。消费者驱动契约(Consumer-Driven Contract,如 Pact):消费者先定义自己对提供方接口的期望(契约),提供方在 CI 中运行契约测试验证是否满足这些契约。当消费者改变契约(接口变更)时,提供方 CI 立即失败,从而在 CI 阶段暴露接口变更问题,避免上线后才发现的集成问题。流程:消费者发布契约 → 提供方在 CI 用契约做 mock 验证 → 契约未通过则构建失败,提示接口变更。分工:契约测试验证"一对一的接口契约"(快、准、无环境依赖);端到端测试(E2E)验证"完整业务流程跨多个服务的集成"(真实环境、覆盖全链路,但慢、脆、依赖环境)。分工原则:契约测试在做 CI 快速反馈接口兼容性,E2E 在关键业务路径上做端到端验证;契约测试覆盖绝大多数接口变更,E2E 覆盖少量核心场景,减少对 E2E 的依赖。

契约测试把"接口兼容性"从"运行时集成才发现"提前到 CI 阶段,消费者驱动契约让接口变更由消费者发起、提供方验证。它与 E2E 的分工是"契约快速反馈接口级 + E2E 验证业务级",两者互补。

#
★★

5. Tenant Test 在多租户隔离测试用例设计。

请说明 Tenant Test(多租户测试)在多租户隔离测试用例设计中的应用?

  • 多租户隔离
  • 测试用例设计
  • 隔离边界验证

多租户(Multi-tenant)系统多个租户共享同一套资源(数据库、缓存、应用),但数据与配置相互隔离。Tenant Test 旨在验证"租户间隔离"是否被正确实现,防止数据泄漏与越权。测试用例设计要点:

  • 数据隔离:租户 A 写入的数据,租户 B 不能读到(查询、列表、详情均隔离);验证不同租户同 ID 数据互不串扰。
  • 权限隔离:租户 A 不能操作租户 B 的资源(越权访问、跨租户写)。
  • 配置隔离:租户间配置(主题、权限、配额)独立。
  • 并发隔离:多租户并发操作不互相影响。
  • 隔离边界:数据库租户列/租户 schema、缓存 key 带租户、队列/消息按租户隔离、对象存储路径隔离。
  • 测试方法:构造两个租户的数据,验证跨租户读写被拒绝;测试租户 ID 注入/篡改、缺失租户 ID、非法租户 ID;验证资源配置(配额、限流)按租户生效。

Tenant Test 聚焦"租户隔离的边界",验证数据、权限、配置、并发在租户间不越界。设计核心是"构造多个租户的状态,验证跨租户访问被拒绝",并覆盖租户标识的注入与篡改漏洞。

#
★★

6. 重试与幂等的配合中指数退避、抖动(jitter)与重试风暴的防护?

请说明重试与幂等的配合,包括指数退避、抖动(jitter)与重试风暴的防护?

  • 重试与幂等配合
  • 指数退避与抖动
  • 重试风暴防护

重试与幂等配合:重试可能造成重复执行(at-least-once),因此被重试的操作必须幂等(重复执行结果一致),否则重试会放大副作用(重复扣款、重复下单)。幂等实现:用业务唯一键/幂等键(Idempotency Key)去重、幂等请求(相同请求返回相同结果)、状态机兜底。指数退避 + 抖动:重试间隔指数递增 + 随机抖动,避免重试风暴。重试风暴防护:设置最大重试次数、指数退避 + 抖动、限制并发、配合熔断(失败率过高停止重试)、传播超时预算、把重试限定在重试窗口内。要点:重试的对象必须幂等(否则重试有害),重试时机用退避+抖动错开,重试上限与熔断兜底防风暴。

重试与幂等是"一体两面":重试解决暂时性失败,幂等保证重试无副作用。指数退避 + 抖动 + 熔断 + 最大重试次数共同防护重试风暴。幂等是重试的前提,否则重试变成放大故障。

#
★★

7. 熔断器的状态转换中 CLOSED→OPEN→HALF-OPEN 的判定参数(阈值/冷却/探测)?

请说明熔断器的状态转换(CLOSED→OPEN→HALF-OPEN)的判定参数(阈值/冷却/探测)?

  • 触发阈值
  • 冷却时间
  • 探测机制

熔断器有三态:

  • CLOSED(关闭):正常放行,统计失败率。判定参数:失败率阈值(failure rate threshold,如 50%)、滑动窗口(统计最近 N 个请求/时间窗口)、最小请求数(minimum call,如 10 个,避免样本不足误判)。当窗口内失败率超过阈值且达到最小请求数,进入 OPEN。
  • OPEN(打开):直接快速失败,不调用下游。判定参数:冷却时间(cooldown / reset timeout,如 5s-60s),此为等待恢复的时间,冷却结束进入 HALF-OPEN。
  • HALF-OPEN(半开):允许少量探测请求(probe,如 1 个或少量)试探下游。判定参数:探测请求数、探测成功率。若探测成功达到阈值(如全部成功)则返回 CLOSED(重置计数);若探测失败则返回 OPEN(重新冷却,重置)。
  • 参数:失败率阈值(灵敏度)、冷却时间(恢复速度)、探测请求数(验证强度)、滑动窗口(统计粒度)。这些参数决定熔断的灵敏度与恢复速度,需结合业务调优。

熔断器状态转换由三组参数驱动:阈值(CLOSED→OPEN)、冷却(OPEN→HALF-OPEN)、探测(HALF-OPEN→CLOSED/OPEN)。参数权衡:阈值高灵敏度低、冷却短恢复快但可能过早放行、探测多验证充分但恢复慢。

#
★★

8. 服务降级与兜底中降级开关、默认值/缓存兜底如何设计,避免雪崩?

请说明服务降级与兜底设计,包括降级开关、默认值/缓存兜底如何设计,以及避免雪崩?

  • 服务降级
  • 降级开关与兜底
  • 避免雪崩

服务降级(fallback/degradation)是在依赖不可用时提供降级响应,保证核心功能可用。设计:

  • 降级开关:预设降级开关(配置/开关中心),当依赖故障或流量超限时手动或自动开启降级,降低对依赖的依赖(如关闭非核心功能、拒绝非关键请求)。
  • 默认值兜底:依赖不可用时返回默认值(如推荐列表为空、价格为默认值、库存为 0),保证接口不报错。
  • 缓存兜底:依赖不可用时返回缓存数据(TTL 内旧数据),保证基本可用。
  • 降级策略:按核心/非核心分级,核心功能保性能、非核心功能降级;区分"读降级"(返回缓存/默认)与"写降级"(丢弃/异步)。
  • 避免雪崩:降级 + 熔断 + 限流 + 超时 + 隔离组合——降级让依赖故障时快速返回兜底,熔断断开故障依赖、限流保护自身、超时限制等待、隔离(bulkhead)防止单一依赖拖垮整线程池。雪崩的根源是"依赖故障未被隔离/兜底,导致故障放大",降级与兜底是防线。

降级与兜底是"故障时给有限但可用的响应",是避免雪崩的关键。降级开关控制开关,默认值/缓存做兜底,配合熔断、限流、超时、隔离形成完整防线。核心是"宁可降级,不可雪崩"。

#
★★

9. 超时预算(Deadline Propagation)与重试中如何避免重试放大超时并造成级联故障?

请说明超时预算(Deadline Propagation)与重试,如何避免重试放大超时并造成级联故障?

  • 超时预算传播
  • 重试放大超时
  • 级联故障防护

超时预算(Deadline Propagation):把请求的总可用时间(deadline)从入口沿调用链传播给下游,每个服务在剩余预算内执行,避免层层叠加超时导致总耗时失控。例如入口设置 2s 总预算,A 服务用 500ms,则传给 B 的剩余预算为 1.5s。重试放大超时:若每个服务都设置独立超时且重试,内层重试会消耗外层预算,导致总耗时超过入口预算,请求堆积、线程池耗尽,造成级联故障。避免方法:重试必须在剩余预算内进行(剩余预算减去已用时间,重试1次需重新计算剩余时间);重试次数有限且退避;超过预算立即失败不再重试;用 deadline 传递(如 gRPC deadline、HTTP 头 X-Deadline)把入口预算传给下游,下游据此截断。级联故障防护:超时预算 + 熔断 + 限流 + 降级 + 隔离组合,避免慢依赖/重试拖垮整个调用链。

超时预算把"总时间"沿调用链传播,让每个环节在剩余时间内执行,重试也受预算约束。若不传播预算,各层独立超时+重试会放大总耗时,造成请求堆积与级联故障。Deadline 是防止重试放大超时的关键。

#
★★

10. 限流与熔断的协作中入口限流保护自身、熔断保护下游,两者如何避免“双重惩罚”与参数冲突?

请说明限流与熔断的协作,入口限流保护自身、熔断保护下游,两者如何避免"双重惩罚"与参数冲突?

  • 限流与熔断的定位
  • 双重惩罚问题
  • 参数协调

限流(Rate Limiting)保护自身:限制进入本服务的请求速率,防止过载耗时保护自身资源;熔断(Circuit Breaker)保护下游:当下游故障时断开,避免把请求继续打到故障下游,保护下游不被拖垮。两者目标不同但协作:限流挡上游(入口),熔断挡下游(出口)。双重惩罚问题:若限流与熔断都基于同一批失败/超时并叠加惩罚,可能让一个依赖的间歇故障既触发限流(拒绝请求)又触发熔断(断开),导致合法请求被过度拒绝,放大故障。避免方法:明确二者职责——限流管"自身容量/上游速率",熔断管"下游健康",两者的触发条件分开(限流看自身 QPS/队列,熔断看下游失败率);避免对同一请求叠加两重拒绝逻辑;参数协调——熔断的失败率统计与限流的通过率不应互相干扰,熔断打开时不应继续限流重试(避免重复惩罚),限流超限拒绝时不应计入熔断失败率(避免把"被限流"误判为"下游故障")。通过合理的阈值与职责划分,让限流与熔断各自负责,避免双重惩罚。

限流守自身、熔断守下游,目标互补。双重惩罚源于"两者统计的失败样本重叠且叠加惩罚"。解决是靠职责分离与参数协调:限流拒绝不计入熔断失败率,熔断打开不叠加限流重试,各自独立触发。

#
★★

11. 优雅停机中摘流量、排空在途请求与等待事务提交的顺序,如何配合就绪探针

请说明优雅停机(Graceful Shutdown)的顺序,包括摘流量、排空在途请求与等待事务提交,以及如何配合就绪探针?

  • 优雅停机顺序
  • 摘流量与排空请求
  • 就绪探针配合

优雅停机是在服务下线/滚动更新时,先停止接收新请求,再排空在途请求,最后释放资源,避免中断在途请求造成数据不一致。顺序:

  1. 摘流量(deregister):从注册中心/负载均衡摘除服务实例,停止接收新请求(更新注册状态、停止新连接)。
  2. 排空在途请求(drain):等待已接收的在途请求处理完成(超时内),停止新的消费/任务。
  3. 等待事务提交:等待当前事务提交完成,避免半途中断事务导致数据不一致。
  4. 释放资源:关闭连接池、线程池、消息消费者,最后关闭进程。 配合就绪探针(readiness probe):就绪探针决定"是否把流量导入该实例"。停机时,先让就绪探针返回失败(不健康),使负载均衡/K8s 停止把新流量路由到该实例,然后执行排空;探针配合实现"先摘流量后排空"。优雅停机需设置停机超时(graceful shutdown timeout),超时后强制终止,避免无限等待。

优雅停机顺序是"摘流量→排空→等待事务→释放"。就绪探针(readiness)控制流量导入,停机时先让探针失败摘流量,再排空在途请求,保证在途事务不中断。超时兜底避免无限等待。

#
★★

12. 数据库迁移与代码发布的顺序中先向后兼容再切换、回滚时如何避免数据不一致

请说明数据库迁移与代码发布的顺序,为什么先向后兼容再切换,以及回滚时如何避免数据不一致?

  • 迁移与发布顺序
  • 向后兼容
  • 回滚安全

数据库迁移(schema/数据变更)与代码发布必须协调,避免新旧版本在迁移后不兼容。正确顺序:先做向后兼容的数据库迁移(如新增字段、新增表、可空字段),再发布新代码(使用新字段),此时旧代码仍能运行(因为新字段可为空/有默认值);待新代码稳定后,再执行破坏性迁移(删除旧字段、改约束)。原因是滚动发布/金丝雀期间新旧代码并存,若先删字段/改类型,旧代码会报错。回滚时避免数据不一致:发布新代码后若需回滚,应保证回滚时数据库 schema 仍兼容旧代码(即保留新增字段、不立即删除,旧代码可无需新字段);数据迁移的回滚要设计逆操作(如新增字段回滚为删除非必需字段,数据填充回滚为可逆),并借助版本控制/迁移工具(Flyway/Liquibase)管理迁移版本,支持前滚与回滚。关键在于"先兼容后破坏、迁移可逆、schema 与代码版本协调"。

迁移与发布顺序的核心是"向后兼容":先加兼容性 schema,再发新代码,最后做破坏性清理。回滚时 schema 需兼容旧代码,迁移工具管理版本与逆操作,避免回滚时数据不一致。

#

13. Bulkhead 在线程池、连接池、进程级隔离的实现差异。

请说明 Bulkhead(舱壁)在线程池、连接池、进程级隔离的实现差异?

  • Bulkhead 思想
  • 线程池/连接池/进程隔离
  • 差异与取舍

Bulkhead(舱壁)模式借鉴船舶舱壁:把资源(线程、连接、进程)划分为多个独立池,某一部分故障/耗尽不影响其他部分,实现故障隔离。实现差异:

  • 线程池隔离:为每个下游依赖分配独立线程池(如 A 用 poolA、B 用 poolB),某依赖的线程耗尽不影响其他依赖;粒度细、灵活,但线程数多、上下文切换开销。
  • 连接池隔离:为每个依赖分配独立连接池,某依赖连接耗尽不影响其他依赖;主要限制连接资源。
  • 进程级隔离:把不同依赖/服务拆到独立进程/容器,故障在进程边界隔离(如 Sidecar、独立部署);隔离最彻底,但资源开销大、部署复杂。 取舍:线程池隔离粒度适中、实现简单(Hystrix 的线程池隔离);连接池隔离针对连接资源;进程级隔离最彻底但成本最高。粒度越细隔离越强但开销越大,需按依赖重要性与资源类型选择。

Bulkhead 是"资源分池"的故障隔离,粒度从线程池、连接池到进程级逐级增强,但开销也递增。选择取决于对隔离程度与资源开销的权衡,以及故障来源(线程耗尽/连接耗尽/进程崩溃)。

#

14. Shared Database 在微服务边界的反模式与适用场景。

请说明 Shared Database(共享数据库)在微服务边界的反模式与适用场景?

  • Shared Database 反模式
  • 微服务边界破坏
  • 适用场景

微服务倡导"每个服务拥有自己的数据库"(database per service),共享数据库(多个服务共用同一数据库/表)是反模式:它让服务间通过数据库强耦合,一个服务的 schema 变更会影响其他服务,破坏了服务边界、独立部署与独立扩展的能力,且容易演变成 Distributed Monolith(表面微服务、内部紧耦合)。问题:schema 变更被放大、无法独立演进、数据库成为瓶颈、权限难以隔离、事务边界模糊。适用场景(例外):读侧共享报表/只读数据库、共享配置/元数据、跨服务查询的共享只读视图、以及小规模/过渡期(如单体拆分初期)。总体应避免共享数据库作为业务写入边界,读侧只读共享可接受。

Shared Database 是微服务反模式,因为破坏服务边界与独立演化。但"只读共享/报表共享"等场景可接受。核心是"写边界分离、读边界可共享"。

#

15. Shared Nothing 在云原生微服务的资源隔离与扩展优势。

请说明 Shared Nothing 架构在云原生微服务的资源隔离与扩展优势?

  • Shared Nothing 架构
  • 资源隔离
  • 独立扩展

Shared Nothing(无共享)架构:每个节点/分区拥有独立的资源(CPU、内存、磁盘、数据),不共享内存或存储,通过消息/网络通信协作。在云原生微服务中,每个服务/实例自带独立资源与数据边界,服务间不共享状态(stateless 或各自独立存储)。优势:

  • 资源隔离:节点/服务故障不影响其他节点,便于故障隔离(某实例宕机不影响他人)。
  • 独立扩展:每个服务可独立水平扩展(按自身负载扩缩容),不受其他服务/共享资源限制。
  • 可伸缩性:无单点共享资源瓶颈,易于水平扩展。
  • 容错:无共享状态,故障单元小,便于替换与恢复。 Shared Nothing 是云原生微服务、无状态服务、分区数据库(如 Cassandra)的基础,配合"无状态 + 独立存储"实现弹性扩展与隔离。

Shared Nothing 的核心是"无共享状态、资源独立",带来资源隔离与独立扩展。它是云原生微服务弹性与容错的基础,代价是跨服务数据共享需通过消息/事件协调。

#

16. 熔断器与超时的分工中超时只能限制等待而不能阻止后续请求,熔断如何实现快速失败保护下游?

请说明熔断器与超时的分工,为什么超时只能限制等待而不能阻止后续请求,以及熔断如何实现快速失败保护下游?

  • 超时的作用与局限
  • 熔断的快速失败
  • 二者分工

超时(timeout)限制单次调用的等待时间,防止请求无限阻塞:设置超时后,若下游未在超时内响应则放弃该请求。但超时只能"限制单次等待",不能"阻止后续请求"——即使下游已故障,每个新请求仍会发起调用、等待超时,大量请求仍会持续打到故障下游,造成资源耗尽与级联。熔断(circuit breaker)则在下游故障率达到阈值后"断开",关闭后续请求(快速失败,不调用下游),直接返回错误/降级,从而保护下游不再被压垮、也保护自身不堆积。分工:超时管"单次等待上限",熔断管"整体放行开关";超时适合限制单次,熔断适合在高失败率下快速失败并让下游恢复。二者配合:超时避免单次阻塞,熔断避免持续压垮;熔断打开后快速失败,冷却后试探恢复。

超时是"单次"粒度,熔断是"整体"粒度。超时只能限制等待,不能阻止后续请求继续失败;熔断通过"失败率触顶即断开并快速失败"保护下游与自身。二者结合才完整。

#

17. 舱壁隔离(Bulkhead)的粒度中线程池/信号量/进程级隔离各适合什么场景?

请说明舱壁隔离(Bulkhead)的粒度,线程池/信号量/进程级隔离各适合什么场景?

  • 线程池隔离
  • 信号量隔离
  • 进程级隔离

Bulkhead 隔离通过把资源分成独立池,防止单一依赖拖垮整体。粒度:

  • 信号量隔离:用信号量(Semaphore)限制并发调用数,不消耗线程、不排队,超限快速失败。适合"不希望占用线程池资源、调用耗时短、只需限并发"的场景(如 Hystrix 的信号量隔离),开销小、实现简单。
  • 线程池隔离:为每个依赖分配独立线程池,依赖耗尽不影响其他依赖(独立线程执行),支持排队与超时。适合"依赖耗时可能长、需要隔离线程资源、需要排队"的场景,隔离彻底但线程开销大。
  • 进程级隔离:把依赖/服务拆到独立进程/容器,故障在进程边界隔离。适合"不同服务/不同语言/需要强隔离"的场景,隔离最彻底但资源与部署成本最高。 选择:信号量适合轻量限并发,线程池适合需排队的耗时依赖,进程级适合强隔离与服务边界。

Bulkhead 三种粒度是"限并发(信号量)→ 独立线程(线程池)→ 独立进程(进程)"的递增,隔离增强但开销递增。选择取决于依赖耗时、并发控制需求与资源预算。

#

18. 韧性测试方法中故障注入(Chaos)、延迟注入与流量回放如何验证系统韧性?

请说明韧性测试方法,故障注入(Chaos)、延迟注入与流量回放如何验证系统韧性?

  • 故障注入(Chaos)
  • 延迟注入
  • 流量回放

韧性测试验证系统在故障下仍能可用(降级、熔断、恢复),方法:

  • 故障注入(Chaos,混沌工程):在生产/类生产环境主动注入故障(杀掉实例、断网、丢包、磁盘故障、依赖故障),验证系统能否自动恢复(如 Chaos Monkey、ChaosBlade、Gremlin)。验证不变性(什么指标必须保持)与故障恢复能力。
  • 延迟注入:人为给依赖注入延迟(latency injection),制造慢依赖,验证超时、熔断、降级、隔离是否生效;验证慢依赖不会拖垮整体(超时/熔断触发)。
  • 流量回放:把生产真实流量(recorded traffic)回放到影子/测试环境,验证系统在真实负载下的行为与韧性,可重放失败流量、异常流量,验证系统对真实流量模式的承受能力。 韧性验证关注:故障注入看"故障后能否恢复",延迟注入看"慢依赖隔离",流量回放看"真实负载下的韧性"。三者组合验证系统在故障、慢、高压下的韧性。

韧性测试用"主动制造故障/延迟/重放流量"来验证系统在异常下的表现。故障注入测恢复能力,延迟注入测慢依赖隔离(超时/熔断),流量回放测真实负载韧性。混沌工程是韧性测试的核心。

#

19. 慢依赖的级联传播模型中一个慢接口会拖垮整个线程池,如何用“独立线程池+快速失败”隔离?

请说明慢依赖的级联传播模型,为什么一个慢接口会拖垮整个线程池,以及如何用"独立线程池 + 快速失败"隔离?

  • 慢依赖级联传播
  • 线程池耗尽
  • 独立线程池 + 快速失败隔离

慢依赖级联传播模型:服务通常用共享线程池处理请求,每个请求会调用下游依赖。若某个下游依赖变慢(响应时间增大),大量请求会阻塞在等待该依赖上,占满线程池线程;新请求无线程可用,整个服务表现为"不可用",即使其他快速依赖也正常。这就是"一个慢接口拖垮整个线程池"——慢依赖的耗时被放大到全局线程池,形成级联故障。隔离方法:独立线程池——为每个依赖分配独立线程池(或按依赖分组),某依赖的慢请求只占用自己的线程池,不占用其他依赖的线程池;快速失败——该依赖的线程池耗尽或超时后立即失败(不排队、不阻塞),或配合信号量/熔断,限制该依赖的并发与超时,让慢依赖只影响自身而不拖垮整体。结合舱壁(Bulkhead)+ 超时 + 熔断:慢依赖被限制在独立池内,超时快速失败,熔断在高失败率下断开,实现局部故障隔离。

慢依赖拖垮全局的根源是"共享线程池 + 无超时/无隔离"。独立线程池让慢依赖只占用自己的资源,快速失败 + 超时 + 熔断防止慢依赖阻塞传播,实现故障隔离。

#

20. liveness 与 readiness 探针中两者分别决定重启与流量摘除,误配如何导致滚动发布卡死

请说明 liveness 与 readiness 探针,两者分别决定重启与流量摘除,以及误配如何导致滚动发布卡死?

  • liveness 探针
  • readiness 探针
  • 误配导致滚动发布卡死

K8s 提供两种探针:

  • liveness(存活探针):决定"是否重启容器",若 liveness 失败,K8s 会重启容器(处理死锁、内存泄漏等不可恢复状态)。
  • readiness(就绪探针):决定"是否把流量路由到该 Pod",若 readiness 失败,K8s 会从 Service 摘除流量(不接收新请求),但不重启。 误配导致滚动发布卡死:若 readiness 探针配置过严(如依赖外部依赖,外部依赖未就绪导致 readiness 一直失败),新 Pod 永远不就绪,滚动发布无法继续推进(新 Pod 不接流量,旧 Pod 不消失),发布会卡死;若 liveness 配置过严(如把正常启动慢的进程误判为失败),会导致容器被反复重启,滚动发布也卡死/repeatedCrashLoopBackoff。关键:readiness 管"能不能接流量",liveness 管"要不要重启",误配(过严/过松、依赖外部)会导致滚动发布的 Pod 永远不就绪或反复重启。

liveness=重启、readiness=流量。readiness 失败导致新 Pod 不接流量、滚动发布卡死;liveness 失败导致反复重启。两者需正确配置,避免依赖外部条件误判。

#

21. 弹性伸缩与冷却期中扩容与缩容的指标选择、冷却时间如何避免抖动

请说明弹性伸缩(Auto Scaling)与冷却期,扩容与缩容的指标选择,以及冷却时间如何避免抖动?

  • 扩容/缩容指标
  • 冷却期
  • 避免抖动

弹性伸缩根据负载自动调整实例数。扩容/缩容指标选择:CPU 使用率、内存、请求 QPS、队列长度、响应延迟、连接数等;扩容可用较敏感的指标(如 CPU > 80%、QPS 超阈值),缩容可用较保守的指标(CPU < 40% 持续一段时间),避免频繁上下。冷却期(cooldown)机制:扩容/缩容后设置冷却时间,在冷却期内不响应新的伸缩请求,避免刚扩容又缩容、刚缩容又扩容的振荡(抖动,thrashing)。原因:实例启动需要时间(启动后负载才降低),冷却期让新实例先稳定再评估;缩容需谨慎(避免把刚扩容的实例又缩掉)。避免抖动方法:设置冷却期、使用平滑/聚合指标(避免单点尖峰)、设置扩缩容的阈值滞回(hysteresis,扩容阈值高于缩容阈值)、缩容延迟(稳定期后再缩)。弹性伸缩目标是"扩得及时、缩得保守、冷却防抖动"。

弹性伸缩的难点是"抖振":用不同感受度的指标 + 冷却期 + 滞回阈值,让扩容及时、缩容保守,避免频繁伸缩。冷却期防止"刚扩又缩、刚缩又扩"。