
1) 【一句话结论】采用“动态分布式令牌桶+漏桶混合算法”,结合Azure Redis Cache存储共享令牌池,通过Lua脚本原子操作处理高并发,动态调整burst_limit和rate_limit应对突发流量,满足每秒1000+请求且平滑处理突发场景。
2) 【原理/概念讲解】老师口吻:咱们先拆解限流的核心需求——处理高并发(每秒1000+)和突发流量(如促销活动)。令牌桶(Token Bucket)像“装令牌的容器”:每秒生成固定令牌(rate_limit),请求消耗令牌,令牌不足则限流,优点是平滑突发(促销时瞬间请求激增,令牌桶能快速生成令牌满足,不会瞬间拒绝);漏桶(Leaky Bucket)像“漏水的桶”:请求按固定速率流入桶,超过则丢弃,优点是保证平均速率稳定(持续高流量不会超过限制)。混合算法结合两者优势:用令牌桶处理突发(平滑),用漏桶保证平均速率(稳定)。为适配Azure云服务的分布式特性(多实例、负载均衡),用Azure Redis Cache存储共享令牌池,确保每个API实例同步限流状态,避免单点故障。同时,动态调整burst_limit(突发令牌数)和rate_limit(令牌生成速率),根据系统负载(CPU利用率、响应时间)和业务场景(促销活动)调整参数。
3) 【对比与适用场景】
| 算法类型 | 定义 | 特性 | 使用场景 | 注意点 |
|---|---|---|---|---|
| 令牌桶 | 每秒生成固定令牌,请求消耗令牌 | 突发流量可平滑处理,但超过速率会等待 | 促销活动、突发流量场景 | 需要等待时间,不适合实时性要求高的场景 |
| 漏桶 | 请求按固定速率流入桶,超过则丢弃 | 平均速率稳定,不会等待 | 持续高流量、需要严格速率限制的场景 | 突发流量会被丢弃,影响业务 |
| 混合算法 | 结合令牌桶和漏桶 | 平滑突发流量+保证平均速率 | 高并发+突发流量场景 | 参数配置复杂,需动态调整,确保工程可行性 |
4) 【示例】
伪代码(含动态调整逻辑与分布式一致性):
import redis
import time
from prometheus_client import Gauge
# 监控指标
REQUEST_RATE = Gauge('api_request_rate', 'Request rate per second')
BURST_LIMIT = Gauge('api_burst_limit', 'Current burst limit')
r = redis.Redis(host='your-redis-endpoint', port=6379, db=0)
def refill_and_consume(key, rate_limit, burst_limit):
"""原子操作补充令牌并检查消耗"""
lua_script = """
local current = tonumber(redis.call('GET', KEYS[1]) or 0)
local refill = tonumber(ARGV[1])
local burst = tonumber(ARGV[2])
local new_tokens = math.min(current + refill, burst)
redis.call('SET', KEYS[1], new_tokens)
return new_tokens
"""
result = r.eval(lua_script, keys=[key], args=[rate_limit, burst_limit])
return result > 0
def adjust_parameters():
"""动态调整burst_limit"""
current_rate = REQUEST_RATE.get_sample_value()
if current_rate > 1.5 * 1000: # 1.5倍rate_limit阈值
new_burst = min(3000, BURST_LIMIT.get_sample_value() + 1000) # 增加burst_limit
else:
new_burst = max(1000, BURST_LIMIT.get_sample_value() - 500) # 降低burst_limit
BURST_LIMIT.set(new_burst)
return new_burst
def handle_request():
"""处理请求,含动态调整与限流逻辑"""
key = "rate_limiter:api_service"
rate_limit = 1000
burst_limit = adjust_parameters()
if refill_and_consume(r, key, rate_limit, burst_limit):
print("请求允许")
REQUEST_RATE.inc()
else:
print("请求被限流,Retry-After:", calculate_retry_after(rate_limit, burst_limit))
def calculate_retry_after(rate_limit, burst_limit):
"""计算Retry-After头"""
current_tokens = r.get(key)
if current_tokens:
current_tokens = int(current_tokens)
remaining_time = (burst_limit - current_tokens) / rate_limit
return max(1, int(remaining_time))
return 1
# 使用示例
if __name__ == "__main__":
for _ in range(1500): # 模拟突发流量
handle_request()
time.sleep(0.001)
5) 【面试口播版答案】
面试官您好,针对Azure云服务API的限流需求,我设计的方案是采用“动态分布式令牌桶+漏桶混合算法”。核心思路是利用Azure Redis Cache存储共享令牌池,通过本地Lua脚本执行令牌补充和消耗的原子操作,确保高并发下不会因锁竞争导致性能下降。同时,令牌桶算法能平滑突发流量(比如促销活动时瞬间请求激增),通过动态调整burst_limit(突发令牌数)和rate_limit(令牌生成速率)应对流量波动,满足每秒1000+的请求处理需求。具体实现上,我们每秒补充固定数量的令牌(比如1000个),请求到来时检查令牌是否充足,不足则返回429状态码并携带Retry-After头(计算逻辑基于当前令牌池状态和请求速率),引导客户端重试。这样既保证了系统的稳定性和突发流量的处理能力,又适配了Azure云服务的分布式特性。
6) 【追问清单】
7) 【常见坑/雷区】