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

问题描述 投票:0回答:1

只是想知道我的想法是否不必要地复杂以及是否有更简单/更好的方法。

我计划使用 Celery 发送请求并从速率受限的 RESTful API 检索数据(每 10 秒 10 个请求)。这是我之前遇到的一个问题的解决方案,我自己编写的 api 包装器(在内部处理速率限制)将为每个视图进行实例化,因此错误地处理了速率限制。

编辑(更多详细信息):
我正在创建一个必须从 RESTful API(即英雄联盟的 API)请求数据的网站。我为 API 编写了一个 python 包装器,它通过计算每个时间间隔发出的请求并等待来处理 API 施加的速率限制。然而,当在 Django 项目中实现我的包装器时,我意识到,当我需要使用 API 时创建包装器类的实例会破坏包装器的速率限制处理,因为每个实例都有单独的请求计数。

我想到的解决方案,可能太复杂,也可能不太复杂,是使用 Celery 来“运行”每个视图都会使用的包装器的单个实例。对于一个看起来非常简单的想法来说,这似乎相对“不合时宜”。也许有一种更简单的方法来始终携带类的单个实例。

django api rest celery rate-limiting
1个回答
0
投票

迟到的答案,但可以帮助其他人寻找类似的东西,恕我直言,使用

Celery
来管理API包装器的单个实例以处理速率受限的API请求可能是一个可行的解决方案,但我认为这有点复杂,以及过度设计的解决方案。
我曾经使用过类似这里提到的东西,我的方法是在 Python Singleton pattern
 包装类中使用 
API
 。这种模式确保只创建该类的一个实例并在所有视图之间共享。因此,您可以维护一个实例来处理速率限制,而不需要 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 包装器实例并将其存储在请求对象中。这样,您就可以在所需的视图中访问同一实例。通过这种方式,您可以将内容保留在 Django 框架内,而不需要像 Celery 这样的外部工具或库。

  • 此外,您还可以使用 Django 的缓存框架来存储 API 包装器实例,确保它在多个视图中可用。您可以使用 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',
    # ...
]
© www.soinside.com 2019 - 2025. All rights reserved.