我正在寻找一种限制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)
这里的简单解决方案是使用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-1调用任务B-2,使用delay()和get()同步等待结果,但这会引入潜在的死锁。
理想情况下,我们可以通过在任务B-1和任务C之间插入任务B-2来动态修改任务链(不知何故,并且反对很多建议,这是不可行的)。
在任务B
中使用自定义速率限制技术我们可以在任务B中实现自己的速率限制,而不是依赖于Celery的每任务速率限制。但是,这会带来更多的复杂性和代码,因此可能,但并不理想。
我很想听听有关哪种策略可能最佳的想法 - 或者是否有一个更简单的解决方案?