流量控制
概述
流量控制(Traffic Control)是一套用于确保系统在有限资源约束下保持稳定、高可用、可预测运行的治理体系。它通过在不同层次对流量进行识别、度量、限制和削峰,实现 资源保护、防止过载、削峰填谷、平滑突发流量、保障核心业务稳定 等目标。
流量控制的本质
流量控制的核心矛盾:系统资源有限 VS 访问流量不可控且可能波动极大
因此需要建立一个能在资源逼近极限时进行自动管控的体系,使得系统在高压场景下仍能 提供可预测、稳定、可退化的服务能力。
其目标包括:
- **资源保护**:保护 CPU、内存、线程池、数据库连接等稀缺资源
- **服务能力匹配**:使下游能力与上游流量匹配
- **风控与业务保护**:避免因为突发流量导致全局性故障
- **系统容错能力**:通过拒绝、降级、排队等方式避免系统雪崩
- **服务质量治理**:防止个别接口抢占过多资源
限流适用边界
适用前提
限流的有效性建立在以下条件之上:
- **存在资源瓶颈**—— 限流保护的是稀缺资源(CPU、内存、线程池、连接池)。无瓶颈则限流徒增复杂度
- **流量不可控**—— 限流的核心价值是管控无法预知的流量冲击。可控流量应优先用资源规划
- **需要公平性**—— 多用户/多调用方共享资源时,限流防止少数方抢占过多资源
- **瓶颈可观测**—— 限流依赖对资源状态的实时感知(CPU、线程池、RT)。若无法感知瓶颈,限流阈值无依据
限流的代价
引入限流需要权衡:
| 问题 | 影响 |
|---|---|
| 误杀正常请求 | 用户体验下降 |
| 增加系统复杂度 | 运维成本提升 |
| 引入额外延迟 | 吞吐量下降 |
| 阈值设置不当 | 资源浪费或保护失效 |
限流维度
同一个请求,可以消耗 1ms CPU,也可以消耗 10 秒线程。QPS 相同,资源消耗可能相差万倍。
核心维度:
- **QPS**——控制流速。下游处理速率恒定,QPS 限制强行将输入速率匹配到下游能力范围
- **并发数**——控制容量。线程池、连接池资源有限,同时占用不能超过这个数
两者是不同的维度,描述同一资源压力的不同侧面。只控 QPS 不控并发:高 QPS + 慢请求 → 线程堆积;只控并发不控 QPS:高并发 + 快请求 → 下游过载。
维度选择由瓶颈位置决定:下游有限 → 侧重 QPS;资源池有限 → 侧重并发;高 QPS + 慢请求 → 两维组合。
流量控制能力模型
流量控制是闭环系统:识别流量特征 → 感知系统状态 → 执行控制行动。三模块对应闭环三环节,缺一则闭环断裂。
流量画像
- 流量分布(分钟级/秒级/突发情况)
- 访问类型(读、写、热点、背景任务)
- 调用链路影响范围
指标体系
系统能力边界依赖关键指标,包括:
- **TPS(事务数/秒)**
- **HPS(请求数/秒)**
- **QPS(查询数/秒)**
- 延迟 P99/P95/P90
- 最大并发数
- IO 带宽、网络带宽
不同业务还存在自定义指标:如游戏的在线人数、IO 服务的最大带宽等。
控制策略
限流策略(控制流量不超限):
- 固定限流(静态阈值)
- 动态限流(根据RT、错误率实时调整)
超额处理策略(流量已超限后如何应对):
- **快速失败**——直接拒绝,减少资源浪费
- **排队等待**——等待资源恢复,适用于可延迟请求
- **柔性限流**——用户无感知:随机延迟、次要请求随机丢弃、前端本地缓存/去抖
- **降级**——关闭非核心接口、返回默认值、限制写操作、去掉昂贵查询
流量承载能力与水位模型
系统承载能力必须通过:
- **全链路压测**
- **历史高峰数据**
- **资源评估(CPU、线程、连接池、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 拥塞控制。
方法:
- 统计 RT P99/P95
- RT 超出阈值 → 自动下降阈值(如降为 ½)
- RT 恢复 → 逐步增加阈值
用于构建:
- 自动调参型限流系统
- 高频量变化系统
分布式限流模型
单机限流:按节点均分配额,各节点独立执行限流。动态调整配额可防止流量倾斜。
全局限流:集中式限流服务统一发放配额。本地缓存作兜底,限流服务异常时 fallback。
货币令牌:请求链路携带额度 token,每调用一次扣减额度,耗尽时向中心申请新额度或多系统协同限流。
选型方法论
按场景选择:
| 场景 | 推荐算法 |
|---|---|
| 强一致速率控制 | 漏桶 |
| 允许突发 | 令牌桶 |
| 并发控制 | 计数器 |
| 可排队任务 | FIFO 队列 |
| 高频波动业务 | 动态限流 |
| 分布式架构 | 全局限流 / 货币令牌 |
演进
流量控制的演进,核心驱动力是流量规模扩张与架构复杂度提升。
| 维度 | 早期 | 演进方向 |
|---|---|---|
| 部署 | 单机限流 | 分布式限流(跨节点协调计数) |
| 阈值 | 静态配置 | 自适应限流(数据驱动反馈,借鉴 TCP 拥塞控制) |
| 响应 | 被动拦截 | 主动预测(流量预测 + HPA 联动) |
| 粒度 | IP/接口级 | 用户画像精细化(区分正常/恶意流量) |
| 架构 | 分层防御散落 | 沿调用链统一协调(上游缓冲,下游兜底) |
关联内容
- [/软件工程/架构/系统设计/可用性.html](/软件工程/架构/系统设计/可用性.html) 流量控制与可用性密切相关,包括限流、降级、熔断等策略保障系统可用性
- [/软件工程/微服务/服务治理/服务容错.html](/软件工程/微服务/服务治理/服务容错.html) 服务容错机制涵盖流量控制中的熔断、限流、降级等策略,是保障系统稳定的重要手段
- [/软件工程/架构/系统设计/网关.html](/软件工程/架构/系统设计/网关.html) 网关承担着流量控制的重要职能,实现统一限流策略、访问频控等功能
- [/软件工程/软件设计/代码质量/软件测试/全链路压测.html](/软件工程/软件设计/代码质量/软件测试/全链路压测.html) 全链路压测是确定流量控制阈值的重要手段,通过压测可确定系统安全水位和极限水位
- [/软件工程/架构/系统设计/伸缩性.html](/软件工程/架构/系统设计/伸缩性.html) 伸缩性与流量控制相互配合,通过指标监控和自动化扩缩容应对流量变化
- [/软件工程/质量工程.html](/软件工程/质量工程.html) 质量工程包含流量控制相关的性能保障措施,如全链路压测、混沌工程等
- [/软件工程/架构/系统设计/监控系统设计.html](/软件工程/架构/系统设计/监控系统设计.html) 监控系统是流量控制的重要支撑,提供QPS、TPS等关键指标监控
- [/软件工程/架构/系统设计/可观测性.html](/软件工程/架构/系统设计/可观测性.html) 可观测性(监控、日志、链路追踪)是流量控制治理的基础,感知层是流量闭环的必要组成
- [/软件工程/容量保障.html](/软件工程/容量保障.html) 容量保障与流量控制密切相关,通过QPS、TPS等指标确定系统容量和限流阈值
- [/软件工程/架构/系统设计/高并发.html](/软件工程/架构/系统设计/高并发.html) 高并发系统设计中需要综合运用流量控制的各种算法和策略
- [/软件工程/架构/系统设计/缓存.html](/软件工程/架构/系统设计/缓存.html) 缓存与流量控制同为系统保护手段,可减轻后端服务压力,缓解流量冲击
- [/计算机网络/运输层.html](/计算机网络/运输层.html) 运输层的流量控制机制(滑动窗口)与应用层流量控制在原理上相通
- [/编程语言/JAVA/JAVA并发编程/线程池.html](/编程语言/JAVA/JAVA并发编程/线程池.html) 线程池是流量控制在单机层面的重要实现,通过限制并发数控制流量
- [/中间件/数据库/分库分表中间件.html](/中间件/数据库/分库分表中间件.html) 数据库中间件的限流功能是流量控制在数据访问层面的具体应用
- [/软件工程/架构/系统设计/混沌工程.html](/软件工程/架构/系统设计/混沌工程.html) 混沌工程可验证流量控制策略在异常场景下的有效性
- [/软件工程/性能工程.html](/软件工程/性能工程.html) 性能工程涉及流量控制相关的性能指标和排队论原理