celery -A proj report
的输出包含在该问题中。master
分支存在该问题。task.py
from celery import Celery
celery = Celery('tasks', broker='pyamqp://guest@localhost//')
@celery.task
def add(x, y):
return x + y
@celery.on_after_configure.connect
def add_periodic():
celery.add_periodic_task(10.0, add.s(2,3), name='add every 10')
if __name__ == '__main__':
add_periodic()
第1步:rabbitmq启动
rabbitmq 1186 1 0 Nov12吗? 00:00:00 / bin / sh / usr / sbin / rabbitmq-server
第二步:执行tasks.py
python tasks.py
第三步:开始击败工人celery -A tasks -l info beat
芹菜节拍v4.0.0(latentcall)开始。
__-... __-_
LocalTime-> 2016-11-12 17:37:58
配置->
。 经纪人-> amqp:// guest:** @localhost :5672 //
。 loader-> celery.loaders.app.AppLoader
。 调度程序-> celery.beat.PersistentScheduler
。 db-> celerybeat-schedule
。 日志文件-> [stderr] @%INFO
。 maxinterval-> 5.00分钟(300s)
[2016-11-12 17:37:58,912:INFO / MainProcess]节拍:正在启动...
我希望调度程序每十秒钟触发一次add()函数。
add()函数不会被触发。
我没有在终端中看到任何异常。 我想念什么吗?
我有同样的问题 :(
您的示例对我来说效果很好。
注意:您的信号处理程序需要接受** kwargs,否则,将来会出现错误。
用你的例子
# file: tasks.py
from celery import Celery
celery = Celery('tasks', broker='pyamqp://guest@localhost//')
@celery.task
def add(x, y):
return x + y
@celery.on_after_configure.connect
def add_periodic(**kwargs):
celery.add_periodic_task(10.0, add.s(2,3), name='add every 10')
我按如下方式启动节拍服务:
$ celery -A tasks beat -l debug
celery beat v4.0.0 (latentcall) is starting.
__ - ... __ - _
LocalTime -> 2016-12-01 11:54:56
Configuration ->
. broker -> amqp://guest:**<strong i="11">@localhost</strong>:5672//
. loader -> celery.loaders.app.AppLoader
. scheduler -> celery.beat.PersistentScheduler
. db -> celerybeat-schedule
. logfile -> [stderr]@%DEBUG
. maxinterval -> 5.00 minutes (300s)
[2016-12-01 11:54:56,511: DEBUG/MainProcess] Setting default socket timeout to 30
[2016-12-01 11:54:56,511: INFO/MainProcess] beat: Starting...
[2016-12-01 11:54:56,517: DEBUG/MainProcess] Current schedule:
<ScheduleEntry: celery.backend_cleanup celery.backend_cleanup() <crontab: 0 4 * * * (m/h/d/dM/MY)>
<ScheduleEntry: add every 10 tasks.add(2, 3) <freq: 10.00 seconds>
[2016-12-01 11:54:56,517: DEBUG/MainProcess] beat: Ticking with max interval->5.00 minutes
[2016-12-01 11:54:56,528: DEBUG/MainProcess] Start from server, version: 0.9, properties: {'information': 'Licensed under the MPL. See http://www.rabbitmq.com/', 'product': 'RabbitMQ', 'copyright': 'Copyright (C) 2007-2016 Pivotal Software, Inc.', 'capabilities': {'exchange_exchange_bindings': True, 'connection.blocked': True, 'authentication_failure_close': True, 'direct_reply_to': True, 'basic.nack': True, 'per_consumer_qos': True, 'consumer_priorities': True, 'consumer_cancel_notify': True, 'publisher_confirms': True}, 'cluster_name': 'rabbit<strong i="12">@grain</strong>', 'platform': 'Erlang/OTP', 'version': '3.6.4'}, mechanisms: [u'AMQPLAIN', u'PLAIN'], locales: [u'en_US']
[2016-12-01 11:54:56,531: INFO/MainProcess] Scheduler: Sending due task add every 10 (tasks.add)
[2016-12-01 11:54:56,534: DEBUG/MainProcess] using channel_id: 1
[2016-12-01 11:54:56,535: DEBUG/MainProcess] Channel open
[2016-12-01 11:54:56,537: DEBUG/MainProcess] beat: Synchronizing schedule...
[2016-12-01 11:54:56,537: DEBUG/MainProcess] tasks.add sent. id->af224838-cf72-4d0d-9076-1c39cdbeffb8
[2016-12-01 11:54:56,537: DEBUG/MainProcess] beat: Waking up in 9.97 seconds.
[2016-12-01 11:55:06,519: INFO/MainProcess] Scheduler: Sending due task add every 10 (tasks.add)
[2016-12-01 11:55:06,520: DEBUG/MainProcess] tasks.add sent. id->907cf307-e36f-455a-97a8-441c79b8ab92
嗨,我有同样的问题。 但是我尝试以编程方式在一个线程中启动celery。 也许是原因。
这是我的主题:
from __future__ import absolute_import, unicode_literals
import threading
from celery import current_app
from celery.bin import worker
app = current_app._get_current_object()
class CeleryThread(threading.Thread):
def __init__(self):
super(CeleryThread, self).__init__()
self.app = app
self.worker = worker.worker(app=self.app)
self.options = {
'broker': 'amqp://guest:guest<strong i="7">@localhost</strong>:5672//',
'loglevel': 'INFO',
'traceback': True,
}
app.add_periodic_task(5.0, test.s('hello'), name='add every 10')
def run(self):
self.worker.run(**self.options)
@app.task
def test(args1):
print args1
和main.py来启动这个
celery_thread = CeleryThread()
# used to kill the thread when the main program stop
# celery_thread.daemon = True
celery_thread.start()
我的控制台输出是
-------------- celery<strong i="14">@ubuntu</strong> v4.0.0 (latentcall)
---- **** -----
--- * *** * -- Linux-4.4.0-51-generic-x86_64-with-Ubuntu-16.04-xenial 2016-12-03 14:33:10
-- * - **** ---
- ** ---------- [config]
- ** ---------- .> app: default:0x7f75775bfc50 (.default.Loader)
- ** ---------- .> transport: amqp://guest:**<strong i="15">@localhost</strong>:5672//
- ** ---------- .> results: disabled://
- *** --- * --- .> concurrency: 4 (prefork)
-- ******* ---- .> task events: OFF (enable -E to monitor tasks in this worker)
--- ***** -----
-------------- [queues]
.> celery exchange=celery(direct) key=celery
[tasks]
. kalliope.core.CrontabManager2.CeleryThread.test
[2016-12-03 14:33:10,458: INFO/MainProcess] Connected to amqp://guest:**@127.0.0.1:5672//
[2016-12-03 14:33:10,466: INFO/MainProcess] mingle: searching for neighbors
[2016-12-03 14:33:11,486: INFO/MainProcess] mingle: all alone
[2016-12-03 14:33:11,515: INFO/MainProcess] celery<strong i="16">@ubuntu</strong> ready.
我会忘记选择吗? 我可以看到您在输出@ask中设置了“调度程序”
在此先感谢您的帮助。
与@ liuallen1981相同的配置和相同的问题。 任何人都知道发生了什么事吗? 现在我必须使用
celery.conf.beat_schedule = {
'do-something-periodically': {
'task': 'tasks.my_task',
'schedule': 3.0,
},
}
而不是将setup_periodic_tasks
函数与on_after_configure.connect
装饰器一起使用。
+1也有这个问题。
+1也有这个问题。
芹菜版本4.0.2(latentcall)
+1也有这个问题。
+1也有这个问题。 继续使用@ liuallen1981的代码进行测试,并得到与我自己的代码相同的结果。
芹菜:4.0.2
要运行定期任务,使用-B
选项启动工作程序时,您还必须调用调度程序:
celery -A proj worker -B
在Django应用程序中使用celery时(从应用程序自动发现任务),您需要使用on_after_finalize
signal而不是on_after_configure
。
参考:
http://stackoverflow.com/questions/40712678/setup-periodic-task/40727526
http://stackoverflow.com/questions/41119053/connect-new-celery-periodic-task-in-django
-B不用于生产,而只是启动Beats调度程序,至少在我看来,该调度程序已在运行。
+1与Celery(4.0.2)有相同的问题
同样的问题在这里...
您只要启动节拍服务,还应该启动一个工作人员来完成任务。
+1
这里同样的问题
同样的问题
并且我尝试在回调中打印一些内容,似乎尚未调用该回调,但是RabbitMQ正常工作(当我在代码中触发任务时工作正常)
@celery.on_after_configure.connect
def setup_periodic_tasks(**kwargs):
print('after connect')
(py35) ➜ celery -A celery.beat beat
celery beat v4.0.2 (latentcall) is starting.
__ - ... __ - _
LocalTime -> 2017-08-08 02:42:18
Configuration ->
. broker -> amqp://**:**@**:5672//
. loader -> celery.loaders.app.AppLoader
. scheduler -> celery.beat.PersistentScheduler
. db -> celerybeat-schedule
. logfile -> [stderr]@%WARNING
. maxinterval -> 5.00 minutes (300s)
我使用Celery config celery.conf.beat_schedule
而不是动态add_periodic_task
来解决此问题,因为我不必动态设置时间表,但仍然不知道为什么会发生此问题。
我遍历该库,发现在触发on_after_configure
信号后,正在创建/附加我的信号侦听器。 (我将信号监听器放置在app/tasks.py
,但它不起作用。)
我认为Django的应用就绪信号可能会在Celery配置后执行,并且到目前为止对我来说效果很好。
注意:我不确定实际上需要什么celery配置以及在配置Celery之前是否有可能app.ready可以启动...但是,我希望它至少会引发运行时错误。
我的app/apps.py
示例代码:
from django.apps import AppConfig
import django.db.utils
from celery_app import app as celery_app
from celery.schedules import crontab
import utils.cron
class MyAppConfig(AppConfig):
name = 'app'
verbose_name = "MyApp"
def ready(self):
print("MyAppConfig.ready invoked.")
import app.signals
print("* * * Setting up periodic tasks!")
import app.models
import app.tasks
for cron in app.models.CronTask.objects.all():
celery_app.add_periodic_task(
crontab(**utils.cron.parse_crontab_expression_to_celery(cron.frequency)),
app.tasks.do_cron.s(cron.id),
name='do cron'
)
请注意,您还需要将INSTALLED_APPS
指向在AppConfig
settings.py
:
INSTALLED_APPS = [
# ...
'app.apps.MyAppConfig',
]
一个好的方法或修补程序可能是编写一个新的装饰器,该装饰器将1)检查是否已配置Celery,如果立即配置,则立即执行; 2)如果未配置Celery,则使用@celery.on_after_configure.connect
添加侦听器。
就目前而言,文档是有问题的,因为我们很多人都遇到了这个问题。
CCing @rustanacexd @viennadd只是这样,如果您仍然需要动态安排任务,可以尝试此修复程序?
把我的两分钱放在那里,我受了这一点,最终不得不重新安排我的一些任务。 我们大约有8个计划的任务应该触发,但是,我注意到会发生以下情况:
例子:
@celery.on_after_configure.connect
def setup_periodic_tasks(**kwargs):
celery.add_periodic_task(5.0, do_thing_b.s(), name='Test B')
celery.add_periodic_task(4.9, do_thing_a.s(), name='Test A')
像这样对它们进行排序意味着do_thing_a
将永远不会触发,因为它将被do_thing_b
覆盖。 最初它们都设置为5
,尽管只有一个会触发(我相信在这种情况下,它会是B,因为它是第一个被添加的)。 接下来,我要做的是将其更改为小数,然后将其偏移.1
以查看是否可以解决该问题。 没有骰子。 然后我命令他们,以便较低的首先射击,较高的第二次射击,最后修复它。 IE:
@celery.on_after_configure.connect
def setup_periodic_tasks(**kwargs):
celery.add_periodic_task(4.9, do_thing_b.s(), name='Test B')
celery.add_periodic_task(5.0, do_thing_a.s(), name='Test A')
我们还使用了一些crontab()
s,尽管有些工作还是有些工作却让人迷惑不解,我怀疑这与上述问题相同。 我还没有完全解决这个问题,因为这些间隔通常设置为每X小时/天发生一次,所以我通常会忘记它们的存在。
也许在文档中提到了这种行为,或者我正陷入另一个困境,尽管这种行为没有多大意义。 作为参考,我们使用Redis代替RMQ和celery 4.1.0。
我能够完成这项工作。 在这里检查我的答案:
@ prasanna-balaraman似乎确实有效,谢谢您的建议!
对我来说同样的问题:我将测试另一个解决方案: https :
闭幕。 如果它仍然出现,并且任何人有任何代码或文档建议,plz随时发送引用此问题的消息。
我花了一段时间才意识到,如果setup_periodic_tasks中引发了任何异常,它将被静默地抑制。
该函数在此处调用: https :
如果发生任何错误,则仅将异常保存在响应中,而不会重新引发或记录:
https://github.com/celery/celery/blob/master/celery/utils/dispatch/signal.py#L276
因此,我的建议是使setup_periodic_tasks尽可能简单。
希望这可以帮助!
@ chiang831您对它有什么建议吗? 如果是这样,请发送公关或在celery-users邮件列表上打开讨论
在on_after_finalize
定义它们对我有用(非django celery应用程序)。
@app.on_after_finalize.connect
def app_ready(**kwargs):
"""
Called once after app has been finalized.
"""
sender = kwargs.get('sender')
# periodic tasks
speed = 15
sender.add_periodic_task(speed, update_leases.s(),
name='update leases every {} seconds'.format(speed))
只是碰到了这一点,以前的解决方案都没有对我有用。 导致这种情况的确切情况令人困惑,并且依赖于ref-counting / gc的行为以及修饰函数的确切生命周期。
默认情况下,Signal.connect仅持有对信号处理程序的弱引用。 这对于Signal对象的其他用例是有意义的(Signal对象的短寿命对象不应通过其信号处理程序使信号保持活动状态),但是在这种情况下非常令人惊讶。
我的特定用例是装饰器,可轻松添加新的定期任务:
def call_every_5_min(task):
@app.on_after_configure.connect
def register_task(sender, **_):
sender.add_periodic_task(collect_every_m*60, task.signature())
<strong i="8">@call_every_5_min</strong>
<strong i="9">@task</strong>
def my_celery_task(_):
pass
解决方法是显式地寻求强大的参考:
def call_every_5_min(task):
def register_task(sender, **_):
sender.add_periodic_task(collect_every_m*60, task.signature())
app.on_after_configure.connect(register_task, weak=False)
文档中的示例仅在修饰后的函数位于模块或类范围内
我建议更改文档以传递weak=False
,这在上面列出的情况下应该可以使用。 我没有在Django上下文中对此进行显式测试。
要运行定期任务,使用
-B
选项启动工作程序时,您还必须调用调度程序:
celery -A proj worker -B
在Django应用程序中使用celery时(从应用程序自动发现任务),您需要使用
on_after_finalize
signal而不是on_after_configure
。参考:
http://stackoverflow.com/questions/40712678/setup-periodic-task/40727526
http://stackoverflow.com/questions/41119053/connect-new-celery-periodic-task-in-django
我的过程python -m celery -A app_name worker -l info --autoscale=20,5 -BE
受阻于的端app_name.celery.py
当使用on_after_finalize
。
与@ liuallen1981相同的配置和相同的问题。 任何人都知道发生了什么事吗? 现在我必须使用
celery.conf.beat_schedule = { 'do-something-periodically': { 'task': 'tasks.my_task', 'schedule': 3.0, }, }
而不是将
setup_periodic_tasks
函数与on_after_configure.connect
装饰器一起使用。
这对我有效。
如果您要解决此问题,请先重新启动Docker引擎,这可能是系统错误的信号
我们应该把这个问题当作不是bug来解决吗?
@auvipy不确定。 看起来是芹菜虫
这是我们必须修复的错误。
最有用的评论
要运行定期任务,使用
-B
选项启动工作程序时,您还必须调用调度程序:celery -A proj worker -B
在Django应用程序中使用celery时(从应用程序自动发现任务),您需要使用
on_after_finalize
signal而不是on_after_configure
。参考:
http://stackoverflow.com/questions/40712678/setup-periodic-task/40727526
http://stackoverflow.com/questions/41119053/connect-new-celery-periodic-task-in-django