Python 芹菜重试消息仍保留在同一个工作进程中
在我的脑海里,我有一个印象,如果芹菜工人得到一个任务,并且它被重试——它保留在工人的记忆中(带有eta)——并且不会返回队列。 因此,如果重试芹菜任务,并且工作人员正忙于处理不同的任务,并且任务eta到达,则必须等待,直到完成其他任务 我试着在文档中查找与我记忆一致的内容,但什么也找不到 我尝试检查的是创建两个任务Python 芹菜重试消息仍保留在同一个工作进程中,python,celery,Python,Celery,在我的脑海里,我有一个印象,如果芹菜工人得到一个任务,并且它被重试——它保留在工人的记忆中(带有eta)——并且不会返回队列。 因此,如果重试芹菜任务,并且工作人员正忙于处理不同的任务,并且任务eta到达,则必须等待,直到完成其他任务 我试着在文档中查找与我记忆一致的内容,但什么也找不到 我尝试检查的是创建两个任务 @app.task(bind=True, name='task_that_holds_worker', rate_limit='4/m', default_ret
@app.task(bind=True, name='task_that_holds_worker', rate_limit='4/m',
default_retry_delay=5 * 60,
max_retries=int(60 * 60 * 24 * 1 / (60 * 5)))
def task_that_holds_worker(self, *args, **kwargs):
import time
time.sleep(50000)
@app.task(bind=True, name='retried_task', rate_limit='2/m',
default_retry_delay=10 * 60,
max_retries=int(60 * 60 * 24 * 1 / (60 * 10)))
def retried_task(self, *args, **kwargs):
self.retry()
最简单的任务,只是检查如果一个任务正忙于其他任务-重试的任务没有被另一个工作者处理
然后,我启动了一个worker,并通过以下方式触发了这两个任务:
from some_app import tasks
from some_app.celery_app import app
current_app = app.tasks
async_result = tasks.retried_task.delay()
import time
time.sleep(20)
async_result = tasks.task_that_holds_worker.delay()
工作人员处理了重试的任务,并重试了它,
然后转到睡眠任务。
然后我启动了另一个worker,我可以看到它没有得到“重试”任务,只有第一个worker
启动的每个工作进程都使用--预取乘数=1--并发性=1
我复制这个的方式有问题吗?
或者这就是芹菜重试任务的行为方式
提前谢谢
- 芹菜:4.1.2
- Python:3.6.2
- Rabbitmq映像:Rabbitmq:3.6.9-management
芹菜/app.task.py
#获取所调用任务的签名
S=来自请求的self.signature\u(
请求,args,kwargs,
倒计时=倒计时,预计到达时间=预计到达时间,重试次数=重试次数,
**选择权
)
如果最大重试次数不是无且重试次数>最大重试次数:
如果exc:
#在Py3上:将使用
#提供了exc的参数(从源代码中提出exc)
使用上下文(exc)引发
提高self.maxretriexedederror(
“无法重试{0}[{1}]args:{2}kwargs:{3}”。格式(
self.name、request.id、S.args、S.kwargs))
ret=重试(exc=exc,当=eta或倒计时)
如果您渴望:
#如果使用apply()急切地执行任务,
#然后重试也必须急切地执行。
S.apply().get()
如果抛出:
提高效率
回程网
尝试:
美国应用异步
除作为exc的例外情况外:
提出拒绝(exc,requeue=False)
如果抛出:
提高效率
回程网
我已经加粗了部分,您可以看到重试是如何工作的。Cellery获取任务请求签名(包括任务名称和任务参数,并设置eta、倒计时和重试次数)。然后芹菜将简单地调用apply\u async
,它将把一个新的任务请求排队发送给代理
您的示例不起作用,因为芹菜工人通常会从代理中提取多个任务请求,因此可能发生的情况是,第一个工人在第二个工人联机之前从代理中抓取了任务 您复制它的方式有错误。除非您有一个特殊的代理,否则芹菜将始终向代理重新发出任务重试请求。工作人员不保留他们尝试执行的任务的任何内存,并且没有添加到重试请求中的数据允许芹菜将任务请求路由回同一工作人员。无法保证或保证同一工作人员将重试其以前看到的任务。您可以在芹菜代码
芹菜/app.task.py
#获取所调用任务的签名
S=来自请求的self.signature\u(
请求,args,kwargs,
倒计时=倒计时,预计到达时间=预计到达时间,重试次数=重试次数,
**选择权
)
如果最大重试次数不是无且重试次数>最大重试次数:
如果exc:
#在Py3上:将使用
#提供了exc的参数(从源代码中提出exc)
使用上下文(exc)引发
提高self.maxretriexedederror(
“无法重试{0}[{1}]args:{2}kwargs:{3}”。格式(
self.name、request.id、S.args、S.kwargs))
ret=重试(exc=exc,当=eta或倒计时)
如果您渴望:
#如果使用apply()急切地执行任务,
#然后重试也必须急切地执行。
S.apply().get()
如果抛出:
提高效率
回程网
尝试:
美国应用异步
除作为exc的例外情况外:
提出拒绝(exc,requeue=False)
如果抛出:
提高效率
回程网
我已经加粗了部分,您可以看到重试是如何工作的。Cellery获取任务请求签名(包括任务名称和任务参数,并设置eta、倒计时和重试次数)。然后芹菜将简单地调用apply\u async
,它将把一个新的任务请求排队发送给代理
您的示例不起作用,因为芹菜工人通常会从代理中提取多个任务请求,因此可能发生的情况是,第一个工人在第二个工人联机之前从代理中抓取了任务 这似乎是eta任务的问题。第一个可用的工作进程倒计时,直到任务到达eta,并且不会将其释放回队列。(预取计数增加并被忽略)
这似乎是eta任务的问题。第一个可用的工作进程倒计时,直到任务到达eta,并且不会将其释放回队列。(预取计数增加并被忽略) 嘿:)谢谢你的回复!在我的例子中,我遗漏了一件事,我认为这件事至关重要。我设置预回迁计数并
# get the signature of the task as called
S = self.signature_from_request(
request, args, kwargs,
countdown=countdown, eta=eta, retries=retries,
**options
)
if max_retries is not None and retries > max_retries:
if exc:
# On Py3: will augment any current exception with
# the exc' argument provided (raise exc from orig)
raise_with_context(exc)
raise self.MaxRetriesExceededError(
"Can't retry {0}[{1}] args:{2} kwargs:{3}".format(
self.name, request.id, S.args, S.kwargs))
ret = Retry(exc=exc, when=eta or countdown)
if is_eager:
# if task was executed eagerly using apply(),
# then the retry must also be executed eagerly.
S.apply().get()
if throw:
raise ret
return ret
try:
S.apply_async()
except Exception as exc:
raise Reject(exc, requeue=False)
if throw:
raise ret
return ret