vault backup: 2026-06-03 10:30:42
This commit is contained in:
+35
-17
@@ -1,16 +1,25 @@
|
||||
# 09 — 限流
|
||||
---
|
||||
tags: [rate-limiting, redis, lua, token-bucket, distributed-system, go]
|
||||
create time: 2026-06-03 10:40
|
||||
---
|
||||
|
||||
> **一句话概括**:Redis Lua 原子令牌桶 + 双层限流 + Fail-Open 降级,保护系统免受过载。
|
||||
# 09. 限流
|
||||
|
||||
## 概述
|
||||
|
||||
Redis Lua 原子令牌桶 + 双层限流 + Fail-Open 降级,保护系统免受过载。
|
||||
|
||||
---
|
||||
|
||||
## 正文
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A["🌐 Request"] --> B["🌍 Global<br/>Limiter"]
|
||||
B -->|pass| C["👤 User<br/>Limiter"]
|
||||
B -->|deny| F["❌ 429"]
|
||||
A["Request"] --> B["Global Limiter"]
|
||||
B -->|pass| C["User Limiter"]
|
||||
B -->|deny| F["429"]
|
||||
B -->|redis-fail| C
|
||||
C -->|pass| D["✅ Handler"]
|
||||
C -->|pass| D["Handler"]
|
||||
C -->|deny| F
|
||||
C -->|redis-fail| D
|
||||
|
||||
@@ -23,7 +32,7 @@ flowchart LR
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ 令牌桶算法
|
||||
## 令牌桶算法
|
||||
|
||||
Gen2D 使用 **Redis + Lua 脚本** 实现分布式令牌桶限流,保证原子性和一致性。
|
||||
|
||||
@@ -75,11 +84,12 @@ return {allowed, tokens, retry_after}
|
||||
- 用完后不补充(`rate = 0` 时跳过 refill)
|
||||
- 等待 key 过期后重置(`Expiration` 控制窗口大小)
|
||||
|
||||
> 💡 **适用场景**:24 小时维度的配额控制,如"每天 30 次提示词优化"。
|
||||
> [!tip] 适用场景
|
||||
> 24 小时维度的配额控制,如"每天 30 次提示词优化"。
|
||||
|
||||
---
|
||||
|
||||
## 🔀 双层限流配置
|
||||
## 双层限流配置
|
||||
|
||||
Gen2D 对核心接口实施**全局限流 + 用户限流**双重保护:
|
||||
|
||||
@@ -126,7 +136,7 @@ type Config struct {
|
||||
|
||||
---
|
||||
|
||||
## 🛡️ Fail-Open 降级
|
||||
## Fail-Open 降级
|
||||
|
||||
当 Redis 不可用时限流器自动降级为 **Fail-Open** 模式:
|
||||
|
||||
@@ -148,11 +158,20 @@ func (l *TokenBucketLimiter) Allow(ctx context.Context, key string) (bool, int,
|
||||
| **Fail-Open** ✅ | 保证可用性,用户体验不受影响 | 可能短暂失去限流保护 |
|
||||
| Fail-Close | 严格限流保护 | Redis 故障导致全站不可用 |
|
||||
|
||||
> 🛡️ **选择 Fail-Open**:在"偶尔超限"和"完全不可用"之间,优先保证服务可用性。
|
||||
> [!question] 为什么选择 Fail-Open 而不是 Fail-Close?
|
||||
>
|
||||
> 这是 **「可用性 vs 安全性」** 的经典抉择。在 Gen2D 的场景中:
|
||||
> - 限流失效的代价:短时间内有人可能超出配额(几分钟到几小时)
|
||||
> - 限流强固化的代价:**所有用户都无法使用服务**
|
||||
>
|
||||
> 显然,前者是可以接受的风险——超出配额的用户可以后续通过账单追缴;而后者意味着业务完全停摆。这种「宁可放宽、不可收紧」的设计哲学在基础设施层非常重要。
|
||||
|
||||
> [!note] 选择 Fail-Open
|
||||
> 在"偶尔超限"和"完全不可用"之间,优先保证服务可用性。
|
||||
|
||||
---
|
||||
|
||||
## 📡 中间件响应
|
||||
## 中间件响应
|
||||
|
||||
限流中间件返回标准化的 HTTP 响应:
|
||||
|
||||
@@ -183,7 +202,7 @@ X-RateLimit-Remaining: 0
|
||||
|
||||
---
|
||||
|
||||
## 📊 指标采集
|
||||
## 指标采集
|
||||
|
||||
限流中间件自动采集 Prometheus 指标:
|
||||
|
||||
@@ -200,8 +219,7 @@ metrics.RateLimitRemainingTokens.WithLabelValues(scope, endpoint).Set(float64(re
|
||||
|
||||
---
|
||||
|
||||
## 🔗 关联文档
|
||||
## 关联文档
|
||||
|
||||
- [← 返回索引](00-index.md)
|
||||
- [10 — 中间件链](10-middleware-chain.md) — 限流中间件在链中的位置
|
||||
- [07 — 可观测性](07-observability.md) — 限流指标和告警规则
|
||||
- [[10-中间件链]] — 限流中间件在链中的位置
|
||||
- [[07-可观测性]] — 限流指标和告警规则
|
||||
|
||||
Reference in New Issue
Block a user