Python速率限制库,使用Redis实现共享状态。
redbucket的Python项目详细描述
红桶
Python速率限制库,使用Redis实现共享状态。在
安装
要安装最新发布的版本:
pip install redbucket
要从GitHub上的主分支安装当前开发版本,请执行以下操作:
^{pr2}$使用
下面的代码片段配置了具有两个速率限制区域的速率限制器:
fromredbucketimportRedisRateLimiter,RateLimit,ZonefromredisimportRedis# Accept up to 5 requests per user per second.# Allow bursts of up to 10 requests.user_zone=Zone('user',rate=5)user_limit=RateLimit(user_zone,burst=10)# Accept up to 20 requests per IP per second.# Allow up to 10 excess requests with a delay.ip_zone=Zone('ip',rate=20)ip_limit=RateLimit(ip_zone,delay=10)redis=Redis()rate_limiter=RedisRateLimiter(redis)rate_limiter.configure(user=user_limit,ip=ip_limit)
我们现在可以使用速率限制器,如下所示:
defexample_operation(user,ip_address):response=rate_limiter.request(user=user,ip=ip_address)ifnotresponse.accepted:raiseException("Rate limit exceeded")# Reject requestifresponse.delay>0:sleep(response.delay)# Wait for delay seconds...# Perform operation
请注意,我们不必为每个区域指定一个键。例如,我们可以 从IP速率限制中排除某些IP地址,同时仍应用 用户限制如下:
defexample_operation(user,ip_address):ifis_whitelisted(ip_address):response=rate_limiter.acquire(user=user)else:response=rate_limiter.acquire(user=user,ip=ip_address)...
实施
默认的RedisRateLimiter
使用Redis的Lua脚本引擎以原子方式
更新速率限制器状态。此实现需要Redis 3.2或更高版本。
对于旧版本的Redis,可以使用RedisTransactionalRateLimiter
。在
在支持的情况下,建议使用基于脚本的实现 每个速率限制请求在一次往返Redis服务器的过程中,而 事务实现执行几个连续的Redis命令 根据要求。在
状态编码
默认情况下,速率限制器状态使用压缩二进制文件存储在Redis中 代表性。您可以切换到JSON以获得效率更低但更高的 人类可读编码。在
rate_limiter = RedisRateLimiter(redis, codec='json')
速率限制模型
redbucket使用了一个受Nginx启发的速率限制模型。 速率限制状态存储在一个或多个区域中。每个区域都有一个名称 和一个基rate。区域表示速率限制keys的命名空间。A rate limit引用一个区域以及两个参数burst和 delay。速率限制器引用一个或多个速率限制。在
为了对操作应用速率限制,应用程序向 通过为每个期望的速率限制指定一个键来实现速率限制器。利率 限制器评估每个速率限制,以确定是否拒绝、延迟或 立即接受请求。如果使用多个利率限制 将应用限制性结果。在
对于基本速率r、突发值b和延迟值的速率限制 d,速率限制器为每个密钥维护一个虚拟计数器 以每秒r请求的速率持续增加到 最大值 b+1。当请求到达时, 速率限制器检查计数器的当前值v。如果 v-1≥0,比率 限制器将计数器减量1并立即接受请求。如果 v−1≥−d, 速率限制器将计数器减量1,并在 延迟 (v-1)/r 秒。否则,,即如果 v−1<;-d, 速率限制器拒绝请求。在
实际上,这意味着从给定密钥的初始空闲状态开始 速率限制器允许 b+1立即请求, 将下一个d请求限制到所需速率,并拒绝任何进一步的请求 请求超过限制。在
与Nginx
如上所述,Red Bucket的速率限制模型是受Nginx和 使用类似的算法。但是,指定突发和延迟的方式是 有点不同。以下配置示例说明了 区别。在
- 在
基本费率限制
# nginxlimit_reqzone=mylimit;
# redbucketRateLimit(zone=mylimit)
在 - 在
延迟突发
# nginxlimit_reqzone=mylimitburst=20;
# redbucketRateLimit(zone=mylimit,delay=20)
在 - 在
无延迟爆发
# nginxlimit_reqzone=mylimitburst=20nodelay;
# redbucketRateLimit(zone=mylimit,burst=20)
在 - 在
两级速率限制
# nginxlimit_reqzone=ipburst=12delay=8;
# redbucketRateLimit(zone=mylimit,burst=8,delay=4)
在
发展
这个项目使用Tox来管理单元测试和其他的虚拟环境 检查。单元测试是使用Pytest框架编写的。在
单元测试需要一个Redis实例。默认情况下测试试图
本地连接6379端口。可以通过设置
REDIS_URL
环境变量。在
export REDIS_URL=redis://localhost:6379
要启动Redis Docker容器来运行测试,可以使用 docker_雷迪斯.sh脚本。例如,对Docker redis运行测试 实例,您可以运行:
./docker_redis.sh tox
也可以在不使用命令的情况下运行脚本并执行要设置的输出 当前shell中的环境变量。在
eval "$(./docker_redis.sh)"
默认情况下,脚本使用redis:alpine
图像。你可以提供
带有-t
标志的redis
图像的不同标记,或其他图像
用-i
命名。在
- 项目
标签: