返回首页

RPS 限制下的 429 错误:泊松和分片

本文分析了平均流量低于限制时 RPS 限制器中持续 429 错误的原因。使用泊松分布,计算了突发概率和条件期望。考虑跨 6 个 Pod 的分片和客户端重试,解释了观察到的 7 RPS 拒绝。

为什么 150 限制下 7 RPS 出现 429:泊松 + 分片
Advertisement 728x90

分布式RPS限流器中429错误的泊松流建模

在平均每秒129次成功请求、限流150 RPS下出现7次429错误时,问题随之而来:为何限流器持续触发?一张40分钟的图表显示,在15秒间隔内错误率保持稳定。请求量的泊松分布解释了这一现象:当λ=136.28时,每秒请求数超过150的概率为11.27%。

计算概率的代码:

def get_prob_at_least(border, lmbd):
    sum = 1
    mult = 1
    for i in range(1, border):
        mult = mult * lmbd / i
        sum += mult
    return 1 - sum * math.exp(-lmbd)

get_prob_at_least(151, 129.01 + 7.27)
# 0.1127

该值在15秒间隔内大于1,与观测图表相符。

Google AdInline article slot

错误的条件期望

简单计算超过限流时的期望请求数得到156.4,而错误率仅为0.6 RPS。这与7.27 RPS的差异需要进一步解释。

条件期望的代码:

def get_expectation_via_conditional_at_least(border, lmbd):
    sum_prob = 0
    exp_sum = 0
    mult = 1
    for i in range(1, 10000):
        mult = mult * lmbd / i
        if (i >= border):
            exp_sum += i * mult
            sum_prob += mult
    return exp_sum / sum_prob

def get_expected_errors_num(events, border):
    return (get_expectation_via_conditional_at_least(border, events) - border) * get_prob_at_least(border, events)

模型调整:重试与分片

考虑每次错误有1次重试(原始流量132.64 RPS)后,错误率升至0.72 RPS——仍显不足。

Google AdInline article slot

关键因素:一个6节点服务(3个数据中心各2个节点)。分片后,每个限流器分配150/6=25 RPS,边界=26。

单个限流器的计算:

limiters_num = 6
retry_num = 2
rps_one_limiter=(129.01 + 7.27 / 2)/limiters_num
border_one_limiter=int(150/limiters_num) + 1

one_limiter_erros = get_expected_errors_num(rps_one_limiter, border_one_limiter)
limited_num = one_limiter_erros * limiters_num * retry_num
# limited_num ≈ 6.85

模型解释了6.85 RPS错误,与观测到的7.27 RPS接近。限流器在无权限同步下运行,通过周期性邻居交换和计数器重置实现。

Google AdInline article slot

分布式限流器的实现特性

可能的选项:

  • 漏桶算法:恒定令牌泄漏。
  • 秒初重置:固定周期,易受流量峰值影响。
  • 动态分配:通过心跳交换计算份额。

在无同步的分片场景中,每个节点独立决定限流,导致整体失败率随分片数线性增加。

核心要点

  • 泊松分布能准确建模无机器人干扰的消费者流量(无限用户的极限情况)。
  • 无同步的RPS限流器分片会按节点比例增加错误率。
  • 客户端重试加剧问题,需要在模型中调整。
  • 条件期望(E[X | X ≥ 边界])对预测失败至关重要。
  • 11%的峰值概率解释了聚合图表中稳定的429错误。

— Editorial Team

Advertisement 728x90

继续阅读