美文网首页python
使用ratelimit限制代码中调用第三方接口的频率

使用ratelimit限制代码中调用第三方接口的频率

作者: 烤奶要加冰 | 来源:发表于2023-03-30 15:00 被阅读0次

背景

调用第三方接口时,常见的问题就是调用频率过快,从而导致一系列的问题:可能会被封IP;可能会被封号;也可能会被限流等问题。

解决思路

最简单的方法:限制一个时间段内的调用频率

ratelimit实现控制调用API的频率

例如以下的测试代码,使用多线程模拟请求调用test2()函数

import time
import threading

def test2():
    time.sleep(3)
    print('调用了函数')


def run_func():
    print('模拟普通请求...')
    test2()


if __name__ == '__main__':
    all_t = []
    for i in range(10):
        t = threading.Thread(target=run_func)
        all_t.append(t)

    for n in all_t:
        n.start()

    for k in all_t:
        k.join()

上面测试代码中,启动的10个线程中在同一个时刻调用了test2()函数,可以理解为1s内请求API10次。下面需要引入ratelimit库控制调用的频率。

import time
from ratelimit import limits

@limits(calls=1, period=1)
def test2():
    time.sleep(3)
    print('调用了函数')

默认情况下,在15min内允许15次请求,超出的请求会被丢弃。在这里设置calls=1,period=1,表示在1s内只允许请求1次。

但是,运行上面代码时,发生了其中一部分线程发生了ratelimit.exception.RateLimitException: too many calls错误,这是为什么呢?

增加阻塞等待

刚刚上面提到,在设置的时间内,请求次数超出设置的值时,其他请求请求会被丢弃。因此,需要处理返回RateLimitException错误的情况。

增加一个装饰器,使得超出的请求阻塞

import time
from functools import wraps

from ratelimit import RateLimitException


def sleep_and_retry(func):
    @wraps(func)
    def wrapper(*args, **kargs):
        while True:
            try:
                return func(*args, **kargs)
            except RateLimitException as exception:
                time.sleep(exception.period_remaining)
    return wrapper

结果

增加上面的装饰器之后,超出的请求也实现堵塞,并能正常相应请求。

完整代码

import threading
import time
from functools import wraps

from ratelimit import limits, RateLimitException


def sleep_and_retry(func):
    @wraps(func)
    def wrapper(*args, **kargs):
        while True:
            try:
                return func(*args, **kargs)
            except RateLimitException as exception:
                time.sleep(exception.period_remaining)
    return wrapper


@sleep_and_retry
@limits(calls=1, period=1)
def test2():
    time.sleep(3)
    print('调用了函数')


def run_func():
    print('模拟普通请求...')
    test2()


if __name__ == '__main__':
    all_t = []
    for i in range(10):
        t = threading.Thread(target=run_func)
        all_t.append(t)

    for n in all_t:
        n.start()

    for k in all_t:
        k.join()

相关文章

  • redission简单实现分布式限流组件

    业务场景 某个三方API接口限制调用频率为200/min,但是某项业务功能中需要频繁的去调用该接口。尽量不去触发限...

  • 构建API服务器4

    限制API调用频率 使用redis-throttle 集成到Rails中,修改config/application...

  • 简洁代码--边界

    代码整洁之道笔记 [TOC] 边界 即自己的代码和第三方的代码的接口适配 使用第三方代码 ①封装 接口提供者和使用...

  • 八、边界

    1.使用第三方代码 接口提供者和接口调用者会在系统边界上出现问题。例如,Map中要求只保存特定的类型,那可以考虑使...

  • 接口调用限制次数

    laravel中间件throttle 频率限制的应用还会回传三个响应头: X-RateLimit-Limit告诉我...

  • 又拍云网关速率限制实践

    速率限制 (Rate Limit) 通过限制调用 API 的频率防止 API 过度使用,保护 API 免受意外或恶...

  • lumen接口访问频率throttle

    由于公司项目对外提供开放平台接口,所以为了防止第三方调用接口太频繁给服务器带来过大的压力,需要对接口调用次数限制,...

  • SpringBoot怎么监听所有请求(保存api日志)

    功能描述 在SpringBoot中如要实现记录接口被调用的频率和生成api日志,以便查看接口使用情况,那么监听所有...

  • 26、【Swift】访问控制 - Access Control

    使用场景:限制其他源文件和模块对代码的访问权限。封装隐藏代码的实现细节,只公开接口给人调用 适用范围:给单个类型(...

  • 基于RateLimiter的服务接口限流实例

    前景回顾:《基于计数器的服务接口限流实例》 一、RateLimit中acquire的使用 在前面这篇文章中,我们使...

网友评论

    本文标题:使用ratelimit限制代码中调用第三方接口的频率

    本文链接:https://www.haomeiwen.com/subject/qxccddtx.html