Python 处理(排队)对调用速率受限的外部API的web服务的请求

Python 处理(排队)对调用速率受限的外部API的web服务的请求,python,web-services,flask,webserver,rate-limiting,Python,Web Services,Flask,Webserver,Rate Limiting,我使用Flask框架公开了一个web服务 此服务用作外部API,该API对每秒应调用的次数有限制 在正常情况下,对my API的多次调用会导致生成多个线程,并调用外部API,而不控制每秒的请求数 是否有一种方法可以将请求排入web服务队列,然后以限制性方式调用外部API 任何其他想法都是受欢迎的 编辑: 我已经知道外部API的速率(每秒1个请求) 如果请求我的API的客户机在获得结果之前必须等待一段时间(几秒/分钟,取决于我的负载),我可以 我不希望我的API客户端得到失败的结果。i、 我不想

我使用Flask框架公开了一个web服务

此服务用作外部API,该API对每秒应调用的次数有限制

在正常情况下,对my API的多次调用会导致生成多个线程,并调用外部API,而不控制每秒的请求数

是否有一种方法可以将请求排入web服务队列,然后以限制性方式调用外部API

任何其他想法都是受欢迎的


编辑:

  • 我已经知道外部API的速率(每秒1个请求)

  • 如果请求我的API的客户机在获得结果之前必须等待一段时间(几秒/分钟,取决于我的负载),我可以

  • 我不希望我的API客户端得到失败的结果。i、 我不想让他们一次又一次地打电话。如果我已经以可能的最大速率访问外部API,那么当速率降低时,对我的API的请求应该排队并进行处理

  • 我读了很多书。我是否能够将web服务调用排入这些队列并在以后处理它们


  • 一种方法是包装请求,这样在找到可接受的速率之前,速率限制失败将导致指数退避

    在下面的示例中,它将继续重试请求,直到请求成功,每次失败时,请求之间的等待时间越来越长,最多允许重试次数(
    n_max
    )。它等待重试请求的秒数呈指数增长(1、2、4、8、16、32等)

    下面是一个使用的示例。捕获错误和识别速率限制错误的细节将取决于用于发出请求的库以及外部api返回的错误类型,但退避算法应相同

    def call_backoff(request_func, n_max=10):
        n = 0
        while n < n_max:
            error = False
            try:
                response = request_func()
            except errors.HttpError as e:
                # You can test here if this is a rate error
                # and not some other error.  You can decide how to handle
                # other errors.
                error = True
                if not_a_rate_error:
                    raise
    
             if response.status_code == 429:
                 error = True
    
             if not error:
                 return response
    
             milli = random.randint(1, 1000)
             secs = (2 ** n) + milli / 1000.0
             time.sleep(secs)
             n += 1
    
        # You can raise an error here if you'd like
        return None
    
    def call\u backoff(请求函数,n\u max=10):
    n=0
    当n
    超出请求时,您希望发生什么情况?是否要阻止对API的请求?或者您会返回自己的
    http429
    响应吗?如果需要,我希望对我的API的请求等待。(排队可能是!?)并在满足外部API的每秒请求标准时返回结果。如果调用我的请求需要几秒钟才能返回,我没有问题。芹菜通常用于启动web请求的长时间运行进程。一般来说,你的客户除了知道请求进入芹菜队列之外不会得到有用的响应,除非你确实在芹菜任务完成时向客户发出警告,比如向他们发送电子邮件,或者使用socket.io或其他方式向他们发送消息。我已经知道外部API的相同速率限制(每秒最多1个请求)。但是,如果超出外部API限制,我不想返回“空”结果。我只想让它们排队并处理得稍微慢一点,然后返回有效结果。使用您的方法,客户端将不得不一次又一次地调用我的API以获得结果,对吗?使用指数回退,它将继续重试重新请求st到外部api,而对您的api的请求被阻塞,因此您的客户端不必重试其请求。每次失败时,它都会等待越来越长的时间重试下一个请求。在我上面给出的示例中(
    n_max
    实际上相当高),它最多将重试10次。第9次尝试后,它将等待15分钟以上再发出第10次请求。但这可能太高了。最好是用错误响应客户端。@Brended这可能也会导致饥饿?当线程等待外部API时,其他线程可能会在和之间访问它因此再次导致等待线程退出?@AmitTomar这是一种可能性,但通常不会保证请求按发送顺序返回。如果希望以更“公平”的方式阻止请求,可以使用共享状态变量来指示api当前是否“阻止”在旧请求完成之前阻止新请求。