RateLimitMiddleware 速率限制中间件文档¶
概述¶
RateLimitMiddleware 是一个基于滑动窗口的速率限制中间件。它在 before_publish 阶段对事件发布频率进行控制,超过限制时自动丢弃事件(不调用 next),并记录警告日志。
支持两种限流模式:
- 全局限流(
per_event=False):所有事件共享一个窗口。 - 按事件名限流(
per_event=True):每种事件名独立计数。
纯内存实现,无外部依赖。
使用场景¶
- 防刷保护:限制客户端高频发布事件。
- 资源保护:防止下游处理器被突发流量压垮。
- 降级策略:在系统负载过高时自动丢弃非关键事件。
- 测试控制:在测试环境中精确控制事件流速率。
函数签名¶
class RateLimitMiddleware(Middleware):
def __init__(
self,
max_requests: int = 100,
window_seconds: float = 1.0,
per_event: bool = False,
) -> None
| 参数 | 类型 | 说明 |
|---|---|---|
max_requests |
int |
时间窗口内允许的最大请求数,默认 100。 |
window_seconds |
float |
滑动窗口大小(秒),默认 1.0。 |
per_event |
bool |
若为 True,按事件名独立计数;否则全局共享一个窗口,默认 False。 |
属性¶
| 属性 | 类型 | 说明 |
|---|---|---|
current_rate |
Dict[str, int] |
返回当前各窗口的请求计数快照。键为事件名(或 "__global__"),值为当前窗口内的请求数。 |
工作流程¶
sequenceDiagram
participant P as 发布者
participant RL as RateLimitMiddleware
participant N as 下游/核心
P->>RL: before_publish(name, data)
RL->>RL: 清理过期时间戳
RL->>RL: 判断当前窗口计数
alt 未超限
RL->>RL: 记录时间戳
RL->>N: next()
else 超限
RL-->>RL: 记录警告日志
Note over RL: return(丢弃事件)
end
before_publish被调用时,先清理窗口外(早于now - window_seconds)的时间戳。- 判断当前窗口内的请求数是否 ≥
max_requests。 - 若未超限:记录当前时间戳,调用
next继续发布流程。 - 若超限:记录
WARNING日志,直接返回(不调用next),事件被丢弃。
使用示例¶
全局限流¶
所有事件共享每秒 100 次的限制:
from infinity_bus.templates.middlewares import RateLimitMiddleware
from infinity_bus import MiddlewareChain
mw = RateLimitMiddleware(max_requests=100, window_seconds=1.0)
chain = MiddlewareChain()
chain.add(mw)
按事件名限流¶
不同事件名独立计数,互不影响:
# mw.ping 每秒最多 50 次,user.login 每秒最多 10 次
mw = RateLimitMiddleware(
max_requests=50,
window_seconds=1.0,
per_event=True,
)
查询当前速率¶
# 查看各窗口的当前请求数
print(mw.current_rate)
# 输出示例:{'__global__': 42} 或 {'mw.ping': 5, 'user.login': 2}
与其他中间件组合¶
先限流再转换,确保转换逻辑只对通过限流的事件生效:
from infinity_bus.templates.middlewares import (
RateLimitMiddleware,
EventTransformMiddleware,
make_field_inject_transform,
)
chain = MiddlewareChain()
chain.add(RateLimitMiddleware(max_requests=10, window_seconds=1.0))
chain.add(EventTransformMiddleware(
make_field_inject_transform(source="trusted")
))
# 执行顺序:限流 → 注入字段 → 核心发布
注意事项¶
- 丢弃无声:超限事件被静默丢弃,不会抛出异常。业务侧如需感知丢弃,可监听日志或自定义中间件。
- 窗口精度:基于
time.monotonic(),不受系统时间调整影响。 - 并发安全:内部使用
asyncio.Lock保护计数操作。 - 内存占用:每个窗口最多保留
max_requests个时间戳,内存开销可控。 - 不含
on_publish_error:速率限制发生在入队前,不会触发错误钩子。
完整示例¶
参见 tests/templates/middlewares/rate_limit_test.py
其中包含了全局限流、按事件名限流、限流后组合转换等场景的测试用例。