Backpressure
解释生产者长期快于消费者时如何通过有界缓冲、阻塞、拒绝、采样或反馈信号限制积压,并把同一原理映射到队列、流和 Agent streaming。
#concept
#evergreen
#backend
#architecture
[!info] related notes
- 所属 MOC:Reliability Engineering MOC、Messaging & Queues MOC
- 相邻概念:Rate Limit、Bulkhead Isolation、Concurrency Control
- Agent Runtime:Agent Runtime MOC
Backpressure
[!abstract] 一句话定义 Backpressure 是当下游处理速度低于上游生产速度时,把“我处理不过来”反馈给上游,并通过减速、排队、拒绝、采样或丢弃控制在途数据,避免无界缓冲最终拖垮系统。
为什么需要背压
Producer: 10,000 items/s
Consumer: 2,000 items/s
Difference: +8,000 items/s accumulates
如果只增加无界 Queue:
latency grows
→ memory / disk grows
→ timeout and retries grow
→ system eventually collapses
Queue 可以吸收短时突发,不能永久解决吞吐失衡。
基本控制方式
| 策略 | 行为 | 适合 |
|---|---|---|
| Block / Await | Producer 等待容量 | 允许传播等待的内部 Pipeline |
| Bounded Queue | 达到容量后阻塞或拒绝 | 大多数后台任务和流处理 |
| Reject / Shed Load | 返回 429/503 或拒绝低价值工作 | 系统过载保护 |
| Drop Oldest / Latest | 丢弃部分事件 | 实时 UI、Telemetry 等允许损失场景 |
| Sample / Coalesce | 合并或采样更新 | 高频进度、状态刷新 |
| Pull / Credit | Consumer 按容量请求数据 | Kafka Fetch、RabbitMQ Prefetch 等 |
| Scale Consumers | 增加处理能力 | 工作可并行且下游仍有容量 |
Rate Limit 与 Backpressure
Rate Limit
→ 根据配额或策略限制进入系统的新请求
Backpressure
→ 根据当前下游容量动态控制在途和生产速度
Rate Limit 可以是预设规则;Backpressure 由实际消费能力和 Queue 状态触发。两者常组合使用。
Queue Depth 不是唯一指标
还应观察:
- Oldest Item Age;
- Producer / Consumer Rate;
- Processing Latency;
- In-flight / Unacked;
- Retry / Redelivery;
- Drop / Reject Rate;
- Downstream Saturation;
- Partition / Key Skew。
同样的 Queue Depth,可能是刚出现的短时突发,也可能是几小时都无法消化的长期积压。
流式响应中的背压
Model Stream
→ Python Runtime
→ Go Gateway
→ Network
→ Browser Render
任何一层消费变慢都可能让 Buffer 增长。可采用:
- 有界 Channel / Queue;
- 合并高频 Token / Progress Event;
- 写 Socket 时 Await Drain;
- Client 断线后传播 Cancellation;
- 对非关键中间事件采样或丢弃。
不能因为 SSE 是“流式”就假设天然没有缓冲和背压问题。合并 Token 应保留原始内容与顺序,不能像覆盖进度百分比那样丢弃文本增量。Socket 的可写信号只反映传输缓冲,不证明浏览器已渲染或用户已消费。
消息系统中的背压
- RabbitMQ:Prefetch 限制未 ACK Delivery;
- Kafka:Consumer Pull、Poll Batch 与 Pause/Resume;
- Async Queue:Worker Concurrency + Bounded Queue;
- HTTP API:429/503、Concurrency Limit、Admission Control。
Prefetch 或暂停 Consumer 只限制投递/读取,不会自动停止 Producer 向 Broker 写入。还需管理 Broker 的积压、保留与入口容量;已接受的持久任务不能因为客户端断开就按临时流的方式删除。
产品机制不同,但目标都是让下游容量成为上游决策的一部分。
常见反模式
- 无界 Queue;
- 只扩 Consumer,不检查共享 DB / API 是否已饱和;
- Queue 满时静默丢高价值任务;
- 所有事件一视同仁,不区分可合并进度和不可丢业务事件;
- 只看平均延迟,不看 Oldest Age 和 P99;
- Client 已断开,后端仍持续生成和缓冲输出。
设计检查表
- Queue / Buffer 有明确上限。
- 满载时是 Block、Reject、Drop 还是 Degrade 已定义。
- 关键业务事件和可丢 Telemetry 使用不同策略。
- Cancellation 能从最慢或已断开的 Consumer 传播上游。
- 指标能区分短时突发、长期容量不足和数据倾斜。
- 扩容前检查下游数据库、网络和第三方配额。