使用Celery和Django访问速率受限的RESTful API

w6mmgewl  于 2023-10-21  发布在  Go
关注(0)|答案(1)|浏览(84)

只是想知道我的想法是否不必要地复杂,是否有更容易/更好的方法。
我计划使用Celery发送请求并从速率受限的RESTful API(每10秒10个请求)中检索数据。这是我之前遇到的一个问题的解决方案,我自己编写的API Package 器在内部处理速率限制,将为每个视图示例化,因此错误地处理速率限制。
编辑(更多详情):
我正在创建一个必须从RESTful API(即英雄联盟的API)请求数据的网站。我已经为API编写了一个python Package 器,它通过计算每个时间间隔发出的请求和等待来处理API施加的速率限制。然而,当我在Django项目中实现我的 Package 器时,我意识到当我需要使用API时,创建我的 Package 器类的示例将打破我的 Package 器的速率限制处理,因为每个示例都有单独的请求计数。
我想到的解决方案,可能太复杂,也可能不太复杂,是使用Celery来“运行”每个视图都会使用的 Package 器的单个示例。对于一个看起来很简单的想法来说,这似乎相对“不太合适”。也许有一种更简单的方法可以在整个过程中携带一个类的示例。

57hvy0tb

57hvy0tb1#

  • 答案很晚,但可以帮助其他人寻找类似的东西 *,恕我直言,使用Celery来管理API Package 器的单个示例,以处理速率受限的API请求可能是一个可行的解决方案,但我认为这是一个有点复杂,过度工程化的解决方案。

我曾经使用过类似这里提到的东西,我的方法是在Python API Package 器类中使用 * Singleton pattern*。此模式确保只创建类的一个示例并在所有视图之间共享。因此,您只需维护一个示例来处理速率限制,而无需Celery。下面是一个简单的例子:

class MyAPIWrapper:
    _instance = None

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super(MyAPIWrapper, cls).__new__(cls)
            cls._instance.init()
        return cls._instance

    def init(self):
        # your API here

# Usage:
api_instance = MyAPIWrapper()

另一个解决方案(从Medium上的谷歌搜索和阅读中获得):

  • 在Django框架中,您可以创建一个自定义中间件,将API Package 器示例封装并存储在请求对象中。这样,您就可以在所需的视图中访问同一个示例。通过这种方式,您可以将事情保持在Django框架内,而不需要像Celery这样的外部工具或库。
  • 此外,您可以使用Django的缓存框架来存储API Package 器示例,确保它在多个视图中可用。您可以使用Django的缓存来存储API示例,并设置缓存超时,以确保在需要时重新创建它。下面是一些代码:
# api_wrapper.py
class RateLimitedAPIWrapper:
    _instance = None

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super(RateLimitedAPIWrapper, cls).__new__(cls)
            # rate limiting logic here
        return cls._instance

# middleware.py
from .api_wrapper import RateLimitedAPIWrapper

class APIMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        self.api_wrapper = RateLimitedAPIWrapper()

    def __call__(self, request):
        # Make the API wrapper available to all views via request
        request.api_wrapper = self.api_wrapper
        response = self.get_response(request)
        return response

# settings.py
MIDDLEWARE = [
    # ...
    'yourapp.middleware.APIMiddleware',
    # ...
]

相关问题