本文目录导读:
- 核心逻辑流程图(通用)
- 框架源码中的降级实现逻辑(以 Sentinel 为例)
- 另一个常见实现:Hystrix(已进入维护期,但逻辑经典)
- 网关层降级(Spring Cloud Gateway)
- 降级实现的3个核心模块
- 源码阅读建议
“源码路由降级”这个说法,通常是指在微服务架构或分布式系统中,当服务调用(RPC/HTTP)发生故障(如超时、异常)时,自动将请求从“真实的服务提供方”切换到“一个备用的、简化逻辑或返回兜底数据的方法”的过程,这里的“源码”可能指代框架源码(如 Spring Cloud、Dubbo、Sentinel)或业务源码。
由于问题比较宽泛,我会从通用实现逻辑和主流框架(Sentinel、Hystrix、Spring Cloud Gateway) 两个层面来拆解。
核心逻辑流程图(通用)
无论是什么框架,降级的本质都是一个策略拦截器:
用户请求 → [过滤器/拦截器] → 判断:是否熔断/降级?
|
├── 否 → 调用真实业务逻辑(真实远程服务/本地方法)
| ├── 成功 → 正常返回
| └── 失败(超时/异常/错误码) → 触发降级逻辑
|
└── 是 → 直接调用降级方法(Fallback方法/兜底数据)
框架源码中的降级实现逻辑(以 Sentinel 为例)
Sentinel 是目前最主流的流量控制/熔断降级组件,其代码实现逻辑非常清晰:
核心骨架:SphU.entry()
当调用一个受保护的资源时,Sentinel 会构建一个责任链(ProcessorSlotChain)。
降级关键类:DegradeSlot
在责任链中,DegradeSlot 负责检查熔断降级,其内部逻辑如下:
- 获取熔断规则:从规则中心(内存或配置中心)获取当前资源的
DegradeRule。 - 状态机判断:
- CLOSED(关闭):正常放行,每次调用后,记录成功/失败/慢调用次数。
- OPEN(开启):直接抛出
DegradeException,触发降级,在open状态会有一个“半开探测”定时任务。 - HALF_OPEN(半开):允许一次请求通过,成功则关闭熔断;失败则继续开启。
- 触发降级:
- 当
getState() == State.OPEN时,DegradeSlot直接返回异常,Entry创建失败。 - 外层代码捕获异常后,调用预设的
fallback()方法。
- 当
降级方法调用(代码层面)
降级方法通常通过 注解(@SentinelResource)或 手动 API 绑定。
// 注解方式(源码中通过 AOP 解析)
@SentinelResource(value = "getUser",
fallback = "getUserFallback", // 降级方法
blockHandler = "getUserBlockHandler") // 流量控制方法
public User getUser(String id) {
// 真实远程调用
return userService.findById(id);
}
// 降级方法必须与原方法签名一致(或加 BlockException 参数)
public User getUserFallback(String id, Throwable e) {
return new User("默认用户"); // 兜底数据
}
源码逻辑:
- AOP 切面拦截
getUser调用。 - 执行
SphU.entry("getUser")。 DegradeSlot报错,捕获DegradeException。- 通过反射调用
getUserFallback方法。
另一个常见实现:Hystrix(已进入维护期,但逻辑经典)
Hystrix 的降级核心在 HystrixCommand 的 run() 和 getFallback() 方法中。
源码逻辑:
- 执行
run():调用真实服务。 - 超时/失败:
- 通过 线程池 或 信号量 隔离,调用
run()。 - 如果超时(
Timeout!)、线程池拒绝(ThreadPoolRejected)、执行异常(Failure),进入getFallback()。
- 通过 线程池 或 信号量 隔离,调用
- 熔断器(CircuitBreaker):
- 基于滑动窗口统计(10秒内请求失败数超过阈值)。
- 熔断开启后,
isCircuitBreakerOpen()返回true,直接跳过run()执行getFallback()。 - 半开状态:允许单个请求探测。
graph TD
A[请求进入] --> B{Circuit Breaker?};
B -- Open/半开(半开且非探测请求) --> C[直接调用 getFallback()];
B -- Closed/半开(探测请求) --> D[尝试调用 run()];
D --> E{run() 成功?};
E -- 成功 --> F[返回结果 并 重置计数器];
E -- 失败/超时/拒绝 --> C;
网关层降级(Spring Cloud Gateway)
在 API 网关层面,降级通常是为某个路由(Route)配置一个 fallback URI。
源码逻辑(基于 Spring Cloud Gateway + Hystrix/Sentinel 集成):
- 过滤链(Filter Chain):
HystrixGatewayFilter或SentinelGatewayFilter。 - 执行转发:向目标服务(如
http://user-service)发起转发。 - 异常/超时:
- 转发失败(连接超时、5xx 错误)。
- 熔断器打开。
- 路由重定向:
- 修改请求的 URI 到
forward:/fallbackHandler或另一个稳定的服务地址。 - 返回统一错误页面或静态缓存数据。
- 修改请求的 URI 到
# 配置示例
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://user-service
filters:
- name: Hystrix
args:
name: userFallback
fallbackUri: forward:/fallback # 降级后转发到网关本地的 /fallback 端点
predicates:
- Path=/api/user/**
降级实现的3个核心模块
- 状态判断(熔断器):
- 基于错误率/慢调用率/异常数(滑动窗口统计)。
- 三种状态:Closed(关闭)、Open(开启)、Half-Open(半开)。
- 隔离机制:
- 线程池隔离(Hystrix):线程池满则降级。
- 信号量隔离(Sentinel/Hystrix):并发数超限则降级。
- 兜底处理(Fallback):
- 调用完整业务逻辑的失败替代方案。
- 常见形式:返回缓存数据、默认值、空结果、错误码。
源码阅读建议
如果你想深入学习,建议按以下顺序阅读相关源码:
| 组件 | 关键类/包 | 查看重点 |
|---|---|---|
| Sentinel | DegradeSlot, CircuitBreaker, ExceptionStrategy |
状态机转换、滑动窗口、半开逻辑 |
| Hystrix | HystrixCommand, HystrixCircuitBreaker, HystrixThreadPool |
线程池隔离、熔断器实现 |
| Spring Cloud | HystrixGatewayFilter, CachingFallbackFilter |
网关层降级路由 |
如果问题是指“业务代码中手动实现降级”,核心就是 try-catch + 条件判断 + 静态数据缓存,也就是所谓的“手动降级”,这两种方式在架构上原理一致,只是框架帮你封装了状态统计与自动切换的逻辑。
标签: 策略路由