流量治理
流量治理解决微服务集群的雪崩问题。核心策略:熔断(快速失败防扩散)、限流(控制流量入口)、降级(返回兜底结果)。
提示
熔断、限流、降级的服务容错策略
雪崩效应
服务依赖链上某一节点故障后,故障沿调用链逐级放大的连锁反应:
根本原因:同步调用 + 无超时控制 + 无熔断保护。
超时控制和限流熔断是防雪崩的基础。
熔断器
熔断器通过三种状态保护故障扩散:
| 状态 | 行为 | 触发条件 |
|---|---|---|
| Closed | 正常请求,统计失败率 | 默认状态 |
| Open | 快速失败,返回 fallback | 失败率超过阈值(默认 50%) |
| Half-Open | 放行少量请求探测 | 熔断持续时间结束 |
Open 状态下主动拒绝请求,避免请求积压拖垮整个链路。
Sentinel vs Hystrix
| 维度 | Hystrix | Sentinel |
|---|---|---|
| 现状 | 停止维护(2018年) | 阿里开源,活跃维护 |
| 隔离方式 | 线程池隔离(资源消耗大) | 信号量 + 并发线程数限流 |
| 限流 | 不支持 | 支持(QPS + 并发数) |
| 控制台 | 简单 | 完善,可动态调整规则 |
新项目使用 Sentinel。
@SentinelResource(value = "getUserById",
fallback = "getUserFallback",
blockHandler = "getUserBlocked")
public User getUserById(Long id) {
return userService.findById(id);
}
public User getUserFallback(Long id, Throwable t) {
return new User(id, "未知用户", "降级返回");
}限流算法
| 算法 | 原理 | 特点 | 适用场景 |
|---|---|---|---|
| 漏桶 | 请求进队列,以固定速率流出 | 流量绝对平滑,不支持突发 | 消息队列消费控制 |
| 令牌桶 | 固定速率生成令牌,有令牌才能通过 | 允许突发,桶内令牌积累 | 秒杀、API 限流 |
| 滑动窗口 | 将单位时间分多格,动态统计 | 精确,解决固定窗口临界问题 | Nginx 限流 |
漏桶强制平滑,超出排队或丢弃;令牌桶允许短时突发,更灵活。
// Guava RateLimiter(令牌桶)
RateLimiter limiter = RateLimiter.create(100.0); // 100 QPS
if (limiter.tryAcquire()) {
process(request);
} else {
return Response.tooManyRequests();
}限流维度
| 维度 | 说明 | 实现 |
|---|---|---|
| QPS 限流 | 每秒请求数上限 | Sentinel 流控规则 |
| 并发数限流 | 同时处理的线程/信号量上限 | 信号量、线程池 |
| 热点参数限流 | 针对特定参数值(如商品 ID)限流 | Sentinel 热点规则 |
| 单机限流 | 每实例独立计数 | Guava、Sentinel 单机模式 |
| 集群限流 | 全集群共享配额 | Sentinel 集群模式(Token Server) |
注意单机 vs 集群:单机限流在 N 个实例下总容量 = 单机阈值 × N,扩容即自动扩容流量;集群限流保证总量精确但引入 Token Server 依赖和额外延迟。多数场景单机限流 + 合理阈值即可。
Sentinel 规则类型
| 规则 | 作用 |
|---|---|
| 流控规则 | QPS/并发数限流,支持直接/关联/链路模式 |
| 熔断规则 | 慢调用比例、异常比例、异常数触发熔断 |
| 热点规则 | 参数维度的精细化限流 |
| 系统保护规则 | 根据系统负载(Load/CPU/RT)自适应限流 |
| 授权规则 | 黑白名单放行/拒绝 |
降级
降级是主动或被动地返回兜底结果,保证核心链路可用。
| 类型 | 触发时机 | 示例 |
|---|---|---|
| 主动降级 | 手动开关 | 大促前关闭推荐功能 |
| 被动降级 | 熔断器触发 | 支付超时,返回「稍后重试」 |
| 兜底降级 | 缓存、默认值 | 查询失败,返回缓存数据 |
核心链路(下单、支付)不能降级。降级要有兜底提示,不能直接返回错误。
隔离
隔离是防止故障扩散的的重要手段,通过资源隔离限制故障影响范围。
舱壁模式为不同服务分配独立资源池,避免一个服务耗尽所有资源。
Hystrix 使用线程池隔离(1000 线程 ≈ 2GB 内存),资源开销大;Sentinel 使用信号量隔离(无需创建额外线程),开销极低。
超时控制
超时是最基础的容错手段,必须为每个远程调用设置超时时间。
feign:
client:
config:
default:
connectTimeout: 1000 # 连接超时 1s
readTimeout: 3000 # 读取超时 3s治理策略优先级
流量治理的各层策略应按优先级依次部署,形成层层设防的容错体系:
限流 → 超时 → 隔离 → 熔断 → 降级限流在最外层拦截超额流量,超时防止请求无限等待,隔离限制故障影响范围,熔断快速切断故障链路,降级在极端情况下返回兜底结果。
请求从用户到服务的完整链路上每一跳的缓存分流策略(客户端、CDN、反向代理、应用、数据库)见 透明多级分流——它和本文的熔断限流降级一外一内,共同构成流量的"疏导 + 保护"。
适用场景
| 场景 | 推荐策略 | 原因 |
|---|---|---|
| 秒杀/抢购 | 限流 + 降级 | 削峰填谷,保护后端 |
| 支付/订单 | 超时 + 熔断 | 防止级联故障 |
| 第三方 API 调用 | 熔断 + 降级 | 外部服务不可控 |
| 大促活动 | 全链路限流 + 主动降级 | 提前关闭非核心功能 |
FAQ
Q: Sentinel 和 Hystrix 该选哪个? A: 新项目统一使用 Sentinel。Hystrix 已于 2018 年停止维护,Sentinel 由阿里开源且活跃维护,支持限流(QPS + 并发数)、熔断、热点参数限流、系统自适应保护等能力,控制台可动态调整规则。已有 Hystrix 项目可逐步迁移到 Sentinel。
Q: 漏桶和令牌桶有什么区别? A: 漏桶以固定速率处理请求,超出部分排队或丢弃,流量绝对平滑;令牌桶以固定速率生成令牌,桶内可积累令牌,允许短时突发流量。大多数场景用令牌桶更合适(如 Guava RateLimiter),需要严格平滑输出时用漏桶(如消息队列消费控制)。
Q: 降级和熔断有什么区别? A: 熔断是自动触发的保护机制,当失败率超过阈值时快速切断请求;降级是主动或被动地返回兜底结果。熔断是降级的一种触发手段——熔断器打开后,请求被降级处理。降级的范围更广,还包括手动开关关闭非核心功能、返回缓存数据等。