流量控制(Traffic Control)是一套用于确保系统在有限资源约束下保持稳定、高可用、可预测运行的治理体系。 它通过在不同层次对流量进行识别、度量、限制和削峰,实现 资源保护、防止过载、削峰填谷、平滑突发流量、保障核心业务稳定 等目标。
流量控制的核心矛盾:系统资源有限 VS 访问流量不可控且可能波动极大
因此需要建立一个能在资源逼近极限时进行自动管控的体系,使得系统在高压场景下仍能 提供可预测、稳定、可退化的服务能力。
其目标包括:
限流的有效性建立在以下条件之上:
引入限流需要权衡:
| 问题 | 影响 |
|---|---|
| 误杀正常请求 | 用户体验下降 |
| 增加系统复杂度 | 运维成本提升 |
| 引入额外延迟 | 吞吐量下降 |
| 阈值设置不当 | 资源浪费或保护失效 |
同一个请求,可以消耗 1ms CPU,也可以消耗 10 秒线程。QPS 相同,资源消耗可能相差万倍。
核心维度:
两者是不同的维度,描述同一资源压力的不同侧面。只控 QPS 不控并发:高 QPS + 慢请求 → 线程堆积;只控并发不控 QPS:高并发 + 快请求 → 下游过载。
维度选择由瓶颈位置决定:下游有限 → 侧重 QPS;资源池有限 → 侧重并发;高 QPS + 慢请求 → 两维组合。
流量控制是闭环系统:识别流量特征 → 感知系统状态 → 执行控制行动。三模块对应闭环三环节,缺一则闭环断裂。
系统能力边界依赖关键指标,包括:
不同业务还存在自定义指标: 如游戏的在线人数、IO 服务的最大带宽等。
限流策略(控制流量不超限):
超额处理策略(流量已超限后如何应对):
系统承载能力必须通过:
确定两类水位:
过低浪费资源,过高会导致雪崩。
阈值回答的是:系统能承受多少?该留多少余量?
压测优先——阈值是测出来的,不是猜出来的。观测数据只能反映"曾经来过多少",无法回答"系统极限是多少"。用真实流量模型压到系统临界点,在重压力区上限设阈值,而非崩溃区。
冗余原则——无法压测时,阈值 = 历史峰值 × (1 + 冗余系数)。冗余覆盖三类不确定性:流量波动、下游衰退、局部故障。核心接口冗余更大。
分层原则——阈值沿调用链路逐层加严:入口宽松、应用精确、下游最严。游阈值总和应低于上游入口处理能力,避免流量堆积。
动态原则——静态阈值迟早失灵。阈值必须可运行时调整,理想形态是基于 RT/错误率的自适应调节。
原理:维护一个当前活动请求数计数器,超过阈值即限流。 典型实现:线程池大小、数据库连接池大小、Nginx worker limit。
算法类型:固定时间窗 (Fixed Window)
限制条件:每 1 分钟限制 100 次请求 (Limit 100 per 1min)
时间轴分布:
|-------------------------|-------------------------|------------------->
0:00 1:00 2:00 时间 (Time)
[ 上一周期 ] [ 当前周期 ]
(Last Cycle) (Current Cycle)
流量爆发点:
0:55 1:00 1:05
●--------|---------●
| | |
+--------+---------+
| 100次 | 100次 |
+--------+---------+
<------- 10秒 ------->
共 200 次请求
问题:在窗口切换的边界点可能出现突发流量未被限制。
时间片 (Time Slices)
---------------------------------------------> (滑动方向)
+------+------+------+------+------+------+------+
| 10 | 7 | 5 | 15 | 0 | 0 | 0 |
+------+------+------+------+------+------+------+
^~~~~~~~~~~~~~~~~~~~~^
滑动窗口 (Window)
滑窗 (Sliding Window)
----------------------------> (数据流/处理方向)
+------+------+------+------+------+------+------+
| 0 | 7 | 5 | 15 | 8 | 5 | 7 |
+------+------+------+------+------+------+------+
^~~~~~~^ ^~~~~~~~~~~~~^
(已滑过) (当前窗口/活跃)
更精确,按前 N 时间片累计请求数判断。
(参考:/软件工程/性能工程.html#排队论)
所有请求入队,由后端消费端按能力处理。 可扩展:
[ 数据输入 / 流量注入 ] <-- 可能是突发、不规律的 (Unregulated)
|
| (滴水/排队)
v
+-------+-------+
| |
| [ 桶 / 队列 ] | <-- 缓冲区 (Buffer),容量为 B
| (已缓存的数据) |
| |
+-------+-------+
|
| (恒定速率流出)
v
[ 数据输出 / 转发 ] <-- 恒定速率 R (Regulated / Constant Rate)
本质:限制处理速率(Rate)
适合:出现瞬时高并发的时候,需要平滑流量处理 的场景。
r 令牌/秒 (填充速率)
|
| /-----------\
v | ( 令牌 ) |
+----+-----------+----+
| |~~~~~| |
| |~~~~~| | <--- 桶容量为 b 个令牌
| |~~~~~| |
+-------+-------+-----+
|
| (取出令牌)
v
数据包 +-------+
========> | 等待 | / \
(流入) | 令牌 | ----> < > ---移除令牌---> 传输至网络
+-------+ \ / (流出)
本质:限制平均速率 + 允许突发流量
借鉴 TCP 拥塞控制。
方法:
用于构建:
单机限流:按节点均分配额,各节点独立执行限流。动态调整配额可防止流量倾斜。
全局限流:集中式限流服务统一发放配额。本地缓存作兜底,限流服务异常时 fallback。
货币令牌:请求链路携带额度 token,每调用一次扣减额度,耗尽时向中心申请新额度或多系统协同限流。
按场景选择:
| 场景 | 推荐算法 |
|---|---|
| 强一致速率控制 | 漏桶 |
| 允许突发 | 令牌桶 |
| 并发控制 | 计数器 |
| 可排队任务 | FIFO 队列 |
| 高频波动业务 | 动态限流 |
| 分布式架构 | 全局限流 / 货币令牌 |
流量控制的演进,核心驱动力是流量规模扩张与架构复杂度提升。
| 维度 | 早期 | 演进方向 |
|---|---|---|
| 部署 | 单机限流 | 分布式限流(跨节点协调计数) |
| 阈值 | 静态配置 | 自适应限流(数据驱动反馈,借鉴 TCP 拥塞控制) |
| 响应 | 被动拦截 | 主动预测(流量预测 + HPA 联动) |
| 粒度 | IP/接口级 | 用户画像精细化(区分正常/恶意流量) |
| 架构 | 分层防御散落 | 沿调用链统一协调(上游缓冲,下游兜底) |