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引用一个区域以及两个参数burstdelay速率限制器引用一个或多个速率限制。在

为了对操作应用速率限制,应用程序向 通过为每个期望的速率限制指定一个键来实现速率限制器。利率 限制器评估每个速率限制,以确定是否拒绝、延迟或 立即接受请求。如果使用多个利率限制 将应用限制性结果。在

对于基本速率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命名。在

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java如何从IBM MQ的JMSException检测可恢复错误   java Lucene6。4.2:找不到类,尝试添加查询。   Java Pdf差异库   在Java中多线程处理我的线程   java将字符串传递给Uri。下载中的parse()   java在列表中查找原语位置   java JPA条件从另一个查询中选择   java中的强制转换和转换   java如何在没有上下文的情况下获取SOAP Web服务(Apache Axis 1.4)的调用客户端的IP地址   java Android IllegalBlockSizeException:解密中最后一个块未完成   java Jersey是否要自定义无效资源路径的错误处理?   如何将JavaCVS web项目转换为基于maven的web项目?   java如何检查通用列表是否与jUnit相等?   arraylist java。util。尝试使用迭代器时发生ConcurrentModificationException错误   使用springsecurity,jsp上的java${u csrf.token}始终为空   sql使用java从临时表中选择数据   spring验证中的java@Notnull和@Pattern无效   java如何使用jQuery将包含对象数组的对象数组传递给Spring MVC控制器?