流量控制基础:核心概念与三大策略

做分布式系统,最怕的是什么?我个人最怕「雪崩效应」。一个小服务挂了,拖垮一大片。我记得刚接手一个电商订单中心,一次大促,下游库存服务响应变慢,结果订单线程全部堵塞,最后整个交易平台瘫了。那次之后我才真正理解——流量控制不是锦上添花,是保命手段。

这一章,咱们聊聊流量控制的三个核心武器:限流、熔断、降级。说白了就是:挡住多余的,保护脆弱的,准备好退路。

一、核心概念对比

先看一张表,把这三个概念摆在一起比较,心里就有谱了。

策略目标触发时机典型手段
限流控制请求速率,防止系统过载请求到达时,速率超过阈值令牌桶、漏桶、计数器
熔断快速失败,避免错误蔓延错误率达到阈值断路器状态机
降级牺牲非核心功能,保障核心可用资源紧张或故障时返回兜底数据、关闭非关键功能
我的习惯:先上线限流,再配置熔断,最后精确设计降级策略。顺序不对,容易引发二次故障。

二、限流策略:把风险挡在门外

限流,顾名思义,限制流量。你在项目中遇到过突发峰值吗?我曾经用接口计数器,结果因为统计窗口边界问题,实际限流效果差得离谱。后来改用令牌桶,稳定多了。

1. 计数器算法

最简单。比如每秒最多100次请求。缺点:窗口边界容易出现流量突刺。

2. 滑动窗口

把时间窗口切小段,平滑统计。比计数器好,但内存开销大一点。

3. 令牌桶(我推荐)

以固定速率往桶里放令牌,请求拿到令牌才能通过。瞬间突发也能平滑。实际使用时,桶容量和速率要根据压测结果调整。

# 伪代码示意:令牌桶
class TokenBucket:
    def __init__(self, rate, capacity):
        self.rate = rate          # 每秒生成令牌数
        self.capacity = capacity  # 桶最大容量
        self.tokens = capacity
        self.last_refill = time.time()

    def allow(self):
        now = time.time()
        elapsed = now - self.last_refill
        self.tokens = min(self.capacity, self.tokens + elapsed * self.rate)
        self.last_refill = now
        if self.tokens >= 1:
            self.tokens -= 1
            return True
        return False

4. 漏桶算法

强制固定速率流出,超出就丢弃。适合用来**削峰填谷**,但不适合处理突发。

注意:限流一定要结合业务场景。我曾经见一个团队对登录接口限流太严,导致正常用户反复重试,反而把后端压死了。限流阈值不是拍脑袋,要基于真实压测+业务容忍度。

三、熔断策略:及时止损

熔断机制,我习惯把它想象成一个电路断路器。正常时闭合,异常多了就断开,让请求快速失败,给小服务喘息时间。

熔断器有三种状态:

  • Closed(闭合):正常调用,计数错误
  • Open(断开):错误达到阈值,直接拒绝请求
  • Half-Open(半开):过一段时间,放一个请求探测恢复情况

举个例子:一个服务调用的错误率超过50%(最近10秒内),熔断器自动打开。所有调用直接返回错误。30秒后进入半开状态,放一个试验请求,成功就闭合,失败就再次打开。

我当时踩过一个坑:熔断器和限流器的超时设置不匹配。限流器那边请求排队,熔断器统计超时错误,结果排队越多错误越多,熔断频繁抖动。解决方案是把超时时间统一管理,并且在熔断器统计时剔除限流排队的时间。

经验值:熔断恢复的半开间隔建议设为服务平均响应时间×3,避免频繁状态切换。

四、降级策略:留好退路

降级,说白了就是「打不过就先认怂」。业务上,降级分两类:

  • 主动降级:预知大流量(比如双11),提前关闭非核心功能(如推荐弹窗、日志实时分析)
  • 被动降级:检测到故障或资源不足,自动切换到兜底方案

我在一个O2O项目中,商品详情页依赖了很多推荐、评论、广告服务。一旦某个依赖挂了,我们降级为显示缓存中的静态文案+统一兜底图片。效果还不错,至少页面能打开,用户能下单。

避坑指南:我曾经设计降级逻辑时,没有考虑幂等性。降级后恢复时,重试请求产生了重复数据。后来总结:降级恢复流程必须保证幂等,并且加上人工确认步骤。

五、三者的关系与协作

限流、熔断、降级不是孤立的。它们组成一个层层递进的防御体系。我画了一张结构图,你可以直观看到它们怎么配合:

流量控制三大策略协作流程 限流层 令牌桶 / 滑动窗口 业务服务 正常处理请求 熔断器 Closed / Open / Half-Open 降级层 兜底数据 / 功能裁剪 降级响应返回 核心逻辑说明 ❶ 请求优先通过限流层 ❷ 进入业务服务正常处理 ❸ 熔断检测错误率,决定是否熔断 ❹ 熔断后自动触发降级策略 三层协同:限流 → 熔断 → 降级,形成完整的流量保护链

六、实践小结

光懂概念不够,落地才是关键。我习惯在设计初期就把限流、熔断、降级方案放进架构图,而不是等出问题了再补。你想想看,如果每层都做好保护,一个小故障根本扩散不起来。

最后说一个原则:降级宁可保守,不要激进。我见过一个团队把整站降级成静态页,结果用户反馈全崩了。其实只要保留核心交易链路就好。记住,降级的目标是让系统「死得体面」,不是「直接死透」。