celery -A proj report
์ ๊ฒฐ๊ณผ๋ฅผ ํฌํจํ์ต๋๋ค.master
์ง์ ์ ๋ฌธ์ ๊ฐ ์์์ ํ์ธํ์ต๋๋ค.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():
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
2 ๋จ๊ณ : tasks.py ์คํ
python tasks.py
step3 : ๋นํธ ์์
์ ์์
celery -A tasks -l info beat
์
๋ฌ๋ฆฌ ๋นํธ v4.0.0 (latentcall)์ด ์์๋ฉ๋๋ค.
__-... __-_
ํ์ง ์๊ฐ-> 2016-11-12 17:37:58
๊ตฌ์ฑ->
. ๋ธ๋ก์ปค-> amqp : // guest : ** @localhost : 5672 //
. ๋ก๋-> celery.loaders.app.AppLoader
. ์ค์ผ์ค๋ฌ-> celery.beat.PersistentScheduler
. db-> celerybeat-schedule
. ๋ก๊ทธ ํ์ผ-> [stderr] @ % INFO
. maxinterval-> 5.00 ๋ถ (300 ์ด)
[2016-11-12 17 : 37 : 58,912 : INFO / MainProcess] beat : ์์ ์ค ...
์ค์ผ์ค๋ฌ๊ฐ 10 ์ด๋ง๋ค 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
์๋ ํ์ธ์, ์ ๋ ๊ฐ์ ๋ฌธ์ ๊ฐ ์์ต๋๋ค. ํ์ง๋ง ์ ๋ ์ค๋ ๋์์ ํ๋ก๊ทธ๋๋ฐ ๋ฐฉ์์ผ๋ก ์ ๋ฌ๋ฆฌ๋ฅผ ์์ํ๋ ค๊ณ ํฉ๋๋ค. ์์ธ ์ผ ์๋ ์์ต๋๋ค.
์ด๊ฒ์ ๋ด ์ค๋ ๋์ ๋๋ค.
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 ์ถ๋ ฅ์ "scheduler"๊ฐ ์ค์ ๋์ด ์์์ ์ ์ ์์ต๋๋ค.
๋์์ ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค.
@ liuallen1981 ๊ณผ ๋์ผํ ๊ตฌ์ฑ ๋ฐ ๋์ผํ ๋ฌธ์ . ๋๊ตฌ๋ ๋ฌด์จ ์ผ์ด ์ผ์ด๋๊ณ ์๋์ง ์์๋ ๋๋ค. ์ง๊ธ์
celery.conf.beat_schedule = {
'do-something-periodically': {
'task': 'tasks.my_task',
'schedule': 3.0,
},
}
on_after_configure.connect
๋ฐ์ฝ๋ ์ดํฐ์ ํจ๊ป setup_periodic_tasks
ํจ์๋ฅผ ์ฌ์ฉํ๋ ๋์ .
+1์ด ๋ฌธ์ ๋ ์์ต๋๋ค.
+1์ด ๋ฌธ์ ๋ ์์ต๋๋ค.
Celery ๋ฒ์ 4.0.2 (latentcall)
+1์ด ๋ฌธ์ ๋ ์์ต๋๋ค.
+1์ด ๋ฌธ์ ๋ ์์ต๋๋ค. @ liuallen1981 ์ ์ฝ๋๋ก ํ ์คํธํ๊ณ ํ ์คํธํ์ผ๋ฉฐ ๋ด ์ฝ๋์ ๋์ผํ ๊ฒฐ๊ณผ๋ฅผ ์ป์์ต๋๋ค.
์ ๋ฌ๋ฆฌ : 4.0.2
์ฃผ๊ธฐ์ ์ธ ์์
์ ์คํํ๋ ค๋ฉด -B
์ต์
์ ์ฌ์ฉํ์ฌ ์์
์๋ฅผ ์์ํ ๋ ์ค์ผ์ค๋ฌ๋ ํธ์ถํด์ผํฉ๋๋ค.
celery -A proj worker -B
์์
์ด ์ ํ ๋ฆฌ์ผ์ด์
์์ autodiscoveredํ๋ ์ฅ๊ณ ์์ฉ ํ๋ก๊ทธ๋จ์ ์
๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ, ๋น์ ์ ์ฌ์ฉํ ํ์๊ฐ on_after_finalize
๋์ ์ ์ ํธ 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)
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋์ ์ผ๋ก add_periodic_task
celery.conf.beat_schedule
๋์ Celery ๊ตฌ์ฑ
๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ดํด ๋ณด๋ on_after_configure
์๊ทธ๋์ด ๋ฐ์ํ ํ ์๊ทธ๋ ๋ฆฌ์ค๋๊ฐ ์์ฑ / ์ฐ๊ฒฐ๋๋ ๊ฒ์ ๋ฐ๊ฒฌํ์ต๋๋ค. (๋ด ์ ํธ ๋ฆฌ์ค๋๋ฅผ app/tasks.py
์ ๋ฐฐ์นํ๋๋ฐ ์๋ํ์ง ์์์ต๋๋ค.)
Django์ ์ฑ ์ค๋น ์ ํธ๋ ์๋ง๋ 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
์ฌ์ฉํ์ฌ ๋ฆฌ์ค๋๋ฅผ ์ถ๊ฐํ๋ ์ ๋ฐ์ฝ๋ ์ดํฐ๋ฅผ ์์ฑํ๋ ๊ฒ์
๋๋ค.
์ฐ๋ฆฌ ์ค ๋ง์ ์ฌ๋๋ค์ด์ด ๋ฌธ์ ์ ๋ถ๋ช ํ๊ธฐ ๋๋ฌธ์ ๋ฌธ์๋ ๋ฌธ์ ๊ฐ๋ฉ๋๋ค.
@rustanacexd @viennadd๋ฅผ ์ฐธ์กฐ ํ์ฌ ์์ ์ ๋์ ์ผ๋ก ์์ฝํด์ผํ๋ ๊ฒฝ์ฐ์ด ์์ ์ ์๋ ํ ์ ์์ต๋๊น?
2 ์ผํธ๋ฅผ ๋ด๋๊ณ , ๋๋ ์ด๊ฒ์ ์กฐ๊ธ์ฉ ๋น ์ ธ์ ๋ด ์์ ์ ์ผ๋ถ๋ฅผ ์ฌ์ ๋ ฌํด์ผํ๋ค. ์คํ๋ ์์ ์ธ ์์ ์ด ์ฝ 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 ์์ ๊ฒ์
๋๋ค). ๋ค์์ผ๋ก 10 ์ง์๋ก ๋ณ๊ฒฝํ๊ณ .1
๋ก ์คํ์
ํ์ฌ ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋๋์ง ํ์ธํ์ต๋๋ค. ์ฃผ์ฌ์๊ฐ ์์ต๋๋ค. ๊ทธ๋ฐ ๋ค์ ๋๋ ๋ฎ์ ์ชฝ์ด ๋จผ์ ๋ฐ์ฌ๋๊ณ ๋์ ์ชฝ์ด ๋ ๋ฒ์งธ๋ก ๋ฐ์ฌ๋๋๋ก ๋ช
๋ นํ์ต๋๋ค. ์ฆ :
@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()
๋ฅผ ์ฌ์ฉํ๊ณ ์์ง๋ง, ๊ทธ๊ฒ๋ค์ ์ด๋ค ์์
์ผ๋ก ์คํ๋๋ ๊ฒ์ ์ผ์ข
์ ๋ฏธ์คํ
๋ฆฌ์ด์ง๋ง, ์ด๋ค ๊ฒ์ ์๋ํ์ง ์์ต๋๋ค. ์์ ๊ฐ์ ๋ฌธ์ ๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์ด๋ฌํ ๊ฐ๊ฒฉ์ ์ผ๋ฐ์ ์ผ๋ก X ์๊ฐ / ์ผ๋ง๋ค ๋ฐ์ํ๋๋ก ์ค์ ๋์ด ์์ผ๋ฏ๋ก ์์ ํ ๋์ ๋ณด์ง ์์์ต๋๋ค.
์๋ง๋ ์ด๋ฐ ์ข ๋ฅ์ ํ๋์ด ๋ฌธ์์ ์ธ๊ธ๋์ด ์๊ฑฐ๋,์ด ํ๋์ด ๊ทธ๋ค์ง ๋ง์ด๋์ง๋ ์์ง๋ง ๋ค๋ฅธ ํ ๋ผ ๊ตด๋ก ๋ด๋ ค๊ฐ ๊ฒ์ ๋๋ค. ์ฐธ๊ณ ๋ก RMQ ๋ฐ celery 4.1.0 ๋์ Redis๋ฅผ ์ฌ์ฉํ๊ณ ์์ต๋๋ค.
๋๋์ด ์ผ์ ํ ์ ์์๋ค. ์ฌ๊ธฐ์์ ๋ด ๋๋ต์ ํ์ธํ์ญ์์ค.
@ prasanna-balaraman ์๋ํ๋ ๊ฒ ๊ฐ์ต๋๋ค. ์ ์ ํด ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค!
๋์๊ฒ ๊ฐ์ ๋ฌธ์ : ๋ค๋ฅธ ์๋ฃจ์ ์ ํ ์คํธํ๊ฒ ์ต๋๋ค : https://stackoverflow.com/a/41119054/6149867
ํ์. ์ฌ์ ํ ๋ํ๋๊ณ ๋๊ตฐ๊ฐ ์ฝ๋ ๋๋ ๋ฌธ์ ์ ์์ด ์์ผ๋ฉด์ด ๋ฌธ์ ๋ฅผ ์ฐธ์กฐํ๋ ํ๋ณด ์๋ฃ๋ฅผ ๋ณด๋ด ์ฃผ์๊ธฐ ๋ฐ๋๋๋ค.
setup_periodic_tasks์์ ์์ธ๊ฐ ๋ฐ์ํ๋ฉด ์กฐ์ฉํ ์ต์ ๋๋ค๋ ๊ฒ์ ๊นจ๋ซ๋ ๋ฐ ์๊ฐ์ด ๊ฑธ๋ ธ์ต๋๋ค.
ํจ์๋ ์ฌ๊ธฐ์์ ํธ์ถ๋ฉ๋๋ค : https://github.com/celery/celery/blob/master/celery/app/base.py#L950
๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ฉด ์์ธ๋ ์๋ต์๋ง ์ ์ฅ๋๊ณ ์ฌ๋ฐ์์ด๋ ๊ธฐ๋ก์ ์์ต๋๋ค.
https://github.com/celery/celery/blob/master/celery/utils/dispatch/signal.py#L276
๊ทธ๋์ ์ ์ ์์ setup_periodic_tasks๋ฅผ ๊ฐ๋ฅํ ํ ๊ฐ๋จํ๊ฒ ์ ์งํ๋ ๊ฒ์
๋๋ค.
๋์์ด ๋์๊ธฐ๋ฅผ ๋ฐ๋๋๋ค!
@ chiang831 ๊ฐ์ ์ ๋ํ ์ ์์ด ์์ต๋๊น? ๊ทธ๋ ๋ค๋ฉด plz๋ ํ๋ณด๋ฅผ ๋ณด๋ด๊ฑฐ๋ ์ ๋ฌ๋ฆฌ ์ฌ์ฉ์ ๋ฉ์ผ ๋ง๋ฆฌ์คํธ์ ๋ํ ํ ๋ก ์ ์ฝ๋ ๋ค.
on_after_finalize
์์ ์ ์ํ๋ ๊ฒ์ด ์ ์๊ฒ ํจ๊ณผ์ ์ด์์ต๋๋ค (๋น ์ฅ๊ณ ์
๋ฌ๋ฆฌ ์ฑ).
@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 ๊ฐ์ฒด (์ ํธ๋ฅผ ์ฐ๊ฒฐํ๋ ๋จ๋ช ๊ฐ์ฒด)์ ๋ค๋ฅธ ์ฌ์ฉ ์ฌ๋ก์ ์ ํฉํ์ง๋ง์ด ๊ฒฝ์ฐ์๋ ๋งค์ฐ ๋๋์ต๋๋ค.
๋ด ํน์ ์ฌ์ฉ ์ฌ๋ก๋ ์๋ก์ด ์ฃผ๊ธฐ์ ์์ ์ ์ฝ๊ฒ ์ถ๊ฐ ํ ์์๋ ๋ฐ์ฝ๋ ์ดํฐ์์ต๋๋ค.
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
์์ ์ด ์ ํ ๋ฆฌ์ผ์ด์ ์์ autodiscoveredํ๋ ์ฅ๊ณ ์์ฉ ํ๋ก๊ทธ๋จ์ ์ ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ, ๋น์ ์ ์ฌ์ฉํ ํ์๊ฐ
on_after_finalize
๋์ ์ ์ ํธ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, }, }
on_after_configure.connect
๋ฐ์ฝ๋ ์ดํฐ์ ํจ๊ปsetup_periodic_tasks
ํจ์๋ฅผ ์ฌ์ฉํ๋ ๋์ .
์ด๊ฒ์ ๋์ ๋๋ฅผ ์ํด ์๋ํฉ๋๋ค.
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ค๋ ๊ฒฝ์ฐ ๋จผ์ ๋์ปค ์์ง์ ์ฌ๋ถํ ํ๋ฉด ์์คํ ๋ฒ๊ทธ ์ ํธ์ผ ์ ์์ต๋๋ค.
์ด ๋ฌธ์ ๋ฅผ ๋ฒ๊ทธ๊ฐ ์๋ ๊ฒ์ผ๋ก ์ข ๋ฃํด์ผํฉ๋๊น?
@auvipy ํ์คํ์ง ์์ต๋๋ค. ์ ๋ฌ๋ฆฌ ๋ฒ๊ทธ ์ธ ๊ฒ ๊ฐ์ต๋๋ค.
์ฐ๋ฆฌ๊ฐ ์์ ํด์ผํ๋ ๋ฒ๊ทธ์ ๋๋ค.
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
์ฃผ๊ธฐ์ ์ธ ์์ ์ ์คํํ๋ ค๋ฉด
-B
์ต์ ์ ์ฌ์ฉํ์ฌ ์์ ์๋ฅผ ์์ํ ๋ ์ค์ผ์ค๋ฌ๋ ํธ์ถํด์ผํฉ๋๋ค.celery -A proj worker -B
์์ ์ด ์ ํ ๋ฆฌ์ผ์ด์ ์์ autodiscoveredํ๋ ์ฅ๊ณ ์์ฉ ํ๋ก๊ทธ๋จ์ ์ ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ, ๋น์ ์ ์ฌ์ฉํ ํ์๊ฐ
on_after_finalize
๋์ ์ ์ ํธon_after_configure
.์ฐธ๊ณ ๋ฌธํ :
http://stackoverflow.com/questions/40712678/setup-periodic-task/40727526
http://stackoverflow.com/questions/41119053/connect-new-celery-periodic-task-in-django