芹菜中的条件限速

时间:2014-12-28 03:48:18

标签: python celery

我正在寻找一种限制Celery任务的方法,我们可以在某些条件下忽略速率限制。

我在Celery中有一个如下所示的任务链:

任务A - >任务B - >任务C

举例说明:

@app.task
def taskA(url):
   # download file from unreliable URL and return path if successful
   try:
       return download_file(url)
   except DownloadError:
       return

@app.task(rate_limit="1/m")
def taskB(file_path):
   # only expect file_path to be set 50% of time
   if file_path:
      return get_remote_api_result(file_path)
   else:
      return

@app.task
def taskC(api_result):
   if api_result:
      archive(api_result)
  • 任务B调用远程API,该API具有API提供程序施加的慢速率限制(1个请求/分钟)。
  • 任务B实际上只在50%的情况下调用远程API,具体取决于任务A的结果。
  • 任务B负责将API结果(或缺少)传递给任务C。

这里的简单解决方案是使用Celery在任务B上设置1 / m的速率限制,但由于我们实际上只是在每个第二个请求上实际调用API,这使链条的速度变慢了两倍。是

我考虑过的几个选项:

  • 使用“看门人”任务。

    链条看起来像这样:

    Task A -> Task B-1 (gatekeeper) -> Task C | ^ v | Task B-2 (Celery rate limited API call)

    任务B-1没有速率限制,并将决定是否应该调用任务B-2。任务B-2将通过Celery获得1 / m的速率限制。

    • 如果调用任务B-2,任务B-1需要等待任务B-2的结果,然后再将其传递给任务C.
    • 如果未调用任务B-2,我们可以立即进入任务C,而不会影响速率限制计数器。

    我们可以让任务B-1调用任务B-2,使用delay()和get()同步等待结果,但这会引入潜在的死锁。

  • 理想情况下,我们可以通过在任务B-1和任务C之间插入任务B-2来动态修改任务链(不知何故,并且反对很多建议,这是不可行的)。

  • 在任务B

    中使用自定义速率限制技术

    我们可以在任务B中实现自己的速率限制,而不是依赖于Celery的每任务速率限制。但是,这会带来更多的复杂性和代码,因此可能,但并不理想。

我很想听听有关哪种策略可能最佳的想法 - 或者是否有一个更简单的解决方案?

0 个答案:

没有答案