深度学习张量基础与PyTorch实战指南
2026/10/29 12:08:04
在高并发系统中,限流器就像闸门,既要保障系统稳定,又不能阻断正常流量。本文将带你从原理出发,手写实现令牌桶与漏桶限流器,构建高性能、可控的 Python 限流组件。
在真实系统中,我们常常面临以下挑战:
这时,限流器就派上用场了。它的目标不是“拒绝服务”,而是“有序接纳”,在保护系统的同时,尽可能多地服务用户。
| 特性 | 漏桶算法 | 令牌桶算法 |
|---|---|---|
| 控制速率 | 固定出水速率 | 固定发放令牌速率 |
| 是否支持突发 | 否 | 是 |
| 实现复杂度 | 简单 | 略高 |
| 适用场景 | 视频流、日志写入等 | API 接口、消息队列等 |
我们将分别实现两个限流器类,并提供使用示例。
importtimeimportthreadingclassLeakyBucket:def__init__(self,capacity,leak_rate):self.capacity=capacity# 桶容量self.leak_rate=leak_rate# 每秒漏出请求数self.water=0# 当前水量self.last_check=time.time()self.lock=threading.Lock()defallow_request(self):withself.lock:now=time.time()elapsed=now-self.last_check leaked=elapsed*self.leak_rate self.water=max(0,self.water-leaked)self.last_check=nowifself.water<self.capacity:self.water+=1returnTrueelse:returnFalsebucket=LeakyBucket(capacity=10,leak_rate=2)# 每秒处理 2 个请求foriinrange(20):ifbucket.allow_request():print(f"[{i}] 请求通过")else:print(f"[{i}] 被限流")time.sleep(0.2)[0] 请求通过 [1] 请求通过 [2] 请求通过 ... [10] 被限流 [11] 被限流 ...classTokenBucket:def__init__(self,capacity,refill_rate):self.capacity=capacity# 最大令牌数self.tokens=capacity self.refill_rate=refill_rate# 每秒补充令牌数self.last_refill=time.time()self.lock=threading.Lock()defallow_request(self):withself.lock:now=time.time()elapsed=now-self.last_refill refill=elapsed*self.refill_rate self.tokens=min(self.capacity,self.tokens+refill)self.last_refill=nowifself.tokens>=1:self.tokens-=1returnTrueelse:returnFalsebucket=TokenBucket(capacity=5,refill_rate=2)# 每秒补充 2 个令牌foriinrange(15):ifbucket.allow_request():print(f"[{i}] 请求通过")else:print(f"[{i}] 被限流")time.sleep(0.3)以 Flask 为例,我们可以将限流器封装为装饰器:
fromflaskimportFlask,jsonify app=Flask(__name__)token_bucket=TokenBucket(capacity=10,refill_rate=5)defrate_limit(func):defwrapper(*args,**kwargs):iftoken_bucket.allow_request():returnfunc(*args,**kwargs)else:returnjsonify({"error":"Too Many Requests"}),429returnwrapper@app.route("/api/data")@rate_limitdefget_data():returnjsonify({"data":"Hello, Python!"})这样就能轻松为接口加上限流保护,防止恶意刷接口。
Decimal替代float,避免时间精度误差。int表示毫秒级时间戳。欢迎在评论区留言交流,我们一起构建更强大的 Python 技术社区!