3.1.20(Redis λΈλ‘컀 λ° λ°±μλ)μ μ¬μ©νκ³ μμΌλ©° μμ
μκ° μ’
λ£λ λ νμ¬ μ€ν μ€μΈ μμ
μ μ€λ¨/μ·¨μνλ λ°©λ²μ μκ³ μΆμ΅λλ€.
μμ μ κ°λ₯ν κ²½μ° μμ
μ FAILEDλ‘ νμνκ³ λ€μμ μμ
μκ° λ€μ μμν λ λ€μ μ€ννμ§ μλ κ²μ
λλ€.
ν λ²μ νλμ μμ μ μ€ν μ€μ΄κ³ μμ μ λΆμμ©μ΄ μμΌλ―λ‘(λ³κ²½ν μ μμ) μμ μλ₯Ό μ£½μ΄λ κ²μ λ¬Έμ κ° λ°μνμ λ μμλλ μ¬μ©μ νλμ΄ λ κ²μ΄λ©° λ€μμ μμ μ λ€μ μ€ννκ³ μΆμ§ μμ΅λλ€. μμ μλ₯Ό μμν λ (λ΄κ° λ―Ώλ κΈ°λ³Έ νμ¨ λμ ...)
λλ μ±κ³΅νμ§ μκ³ http://stackoverflow.com/a/8230470 μ μλνμ΅λλ€.
λν λΆνΈ λ¨κ³μμ μ μ΄ μΈν°νμ΄μ€ λλ μμ
μλ₯Ό μ¬μ©νμ¬ λͺ κ°μ§λ₯Ό μλνμ΅λλ€.
from celery import Celery, bootsteps
from celery.task.control import revoke
# TODO : configuration for tests...
class BootPyrosNode(bootsteps.StartStopStep):
def __init__(self, worker, **kwargs):
logging.warn('{0!r} is starting from {1}'.format(worker, __file__))
[...]
def create(self, worker):
return self
def start(self, worker):
# our step is started together with all other Worker/Consumer
# bootsteps.
pass # not sure in which process this is run.
def stop(self, worker):
# the Consumer calls stop every time the consumer is restarted
# (i.e. connection is lost) and also at shutdown. The Worker
# will call stop at shutdown only.
logging.warn('{0!r} is stopping. Attempting abort of current tasks...'.format(worker))
for req in worker.state.active_requests:
# worker.app.control.revoke(req.id, terminate=True) # not working
# revoke(req.id, terminate=True) # not working
self.node_proc.shutdown()
μ΄ λ°©λ²μΌλ‘ μ€μΉ:
celeros_app = Celery()
# setting up custom bootstep to start ROS node and pass ROS arguments to it
celeros_app.steps['worker'].add(BootPyrosNode)
celeros_app.user_options['worker'].add(Option('-R', '--ros-arg', action="append", help='Arguments for ros initialisation'))
κ·Έλ¬λ λ΄ μμ μ μ·¨μ/μ€λ¨ν μ μλ κ² κ°μ΅λλ€(μλ§λ μμ μκ° μ€μ§ ν μ μ΄ λ©μμ§λ₯Ό μ²λ¦¬νμ§ μκΈ° λλ¬ΈμΌ μ μμ΅λκΉ? ). κ·Έλ¦¬κ³ μμ΄λμ΄κ° λΆμ‘±ν©λλ€.
λ λ³΄κ³ μΆλ€λ©΄ https://github.com/asmodehn/celerosμμ μ½λλ₯Ό νμΈνμΈμ.
λ°©λ²μ΄ μμ΅λκΉ, μλλ©΄ μμ§ λΆκ°λ₯ν μ¬μ©μ μ μμ λκΉ?
μ’ λ£ μ€μλ μ격 μ μ΄ λͺ λ Ήμ μμ μκ² λ³΄λΌ μ μμ΅λλ€. μμ μ λ΄λΆλ₯Ό μ¬μ©νμ¬ μμ μ μ·¨μν΄μΌ ν©λλ€(celery/worker/control.pyμμ μ격 μ μ΄ λͺ λ Ήμ΄ κ΅¬νλλ λ°©λ² μ°Έμ‘°).
λν λΆνΈ λ¨κ³κ° νμ μμ‘΄νλμ§ νμΈνμ¬ stop()
λ©μλκ° μ’
λ£ μ€μ λ¨Όμ νΈμΆλλλ‘ ν΄μΌ ν©λλ€.
class Step..:
requires = ('celery.worker.components:Pool',)
κ°μ¬ ν΄μ !
μμ
μ μ’
λ£ μ μ€ν μ€μΈ μμ
μ μ·¨μν μ μμμ΅λλ€. :
def stop(self, worker):
# the Consumer calls stop every time the consumer is restarted
# (i.e. connection is lost) and also at shutdown. The Worker
# will call stop at shutdown only.
logging.warn('{0!r} is stopping. Attempting termination of current tasks...'.format(worker))
# Following code from worker.control.revoke
task_ids = []
terminated = set()
# cleaning all reserved tasks since we are shutting down
signum = _signals.signum('TERM')
for request in [r for r in worker.state.reserved_requests]:
if request.id not in terminated:
task_ids.append(request.id)
terminated.add(request.id)
logger.info('Terminating %s (%s)', request.id, signum)
request.terminate(worker.pool, signal=signum)
# Aborting currently running tasks, and triggering soft timeout exception to allow task to clean up.
signum = _signals.signum('USR1')
for request in [r for r in worker.state.active_requests]:
if request.id not in terminated:
task_ids.append(request.id)
terminated.add(request.id)
logger.info('Terminating %s (%s)', request.id, signum)
request.terminate(worker.pool, signal=signum) # triggering SoftTimeoutException in Task
if terminated:
terminatedstr = ', '.join(task_ids)
logger.info('Tasks flagged as revoked: %s', terminatedstr)
self.node_proc.shutdown()
λ¨Όμ reserved_requests λͺ©λ‘μμ μμ μ μ·¨μνμ¬ κΈ°λ³Έμ μΌλ‘ μ’ λ£ μ§μ μ λκΈ° μ€μΈ μμ μ΄ μΈκ³λλ κ²μ λ°©μ§ν©λλ€.
κ·Έλ° λ€μ νμ± μμ²μ μ·¨μνκ³ μμ μμ μ 리 λμμ νΈλ¦¬κ±°ν μ μλλ‘ μμ μμ SoftTimeLimitExceeded μμΈλ₯Ό νΈλ¦¬κ±°ν©λλ€. acks_late(ν λ²μ νλμ μμ λ§ μ€ννκΈ° μν΄)λ₯Ό μ¬μ©νκ³ μμΌλ―λ‘ μμ μ μ¬λ°λ₯΄κ² μΉμΈνκ³ λ€μμ μμ μλ₯Ό μμν λ λ€μ μμνμ§ μλλ‘ μμ μμ 볡κ·νκ±°λ λ°μμμΌμΌ ν©λλ€.
μ€λ¨ κ°λ₯ν μμ μ μ¬μ©νκ³ μμ§λ§ μ€λ¨ λμμ μ¬μ©μκ° μλμ μΌλ‘ μμ μ μ€λ¨νκ³ μμ€ν μμ μΌλΆ 볡μ‘/κΈ΄ μ 리λ₯Ό μνν΄μΌ ν λ μ½λ©λ©λλ€. μ΄ κ²½μ°λ μμ μκ° μ’ λ£λλ κ²κ³Ό κ°μΌλ©°, μ΄ κ²½μ° νμ¬ μμ μ 빨리 μ€ν¨νκ² λ§λ€κ³ μΆμ΅λλ€.
λλ μ΄κ²μ΄ μλ¬λ¦¬μμ μΌμ νλ μ μ ν λ°©λ²μ΄λΌκ³ μκ°ν©λκΉ?
ν₯ν λ²μ μμλ Task ν΄λμ€μμ λμμ κ°λ¨ν μ¬μ μν μ μμΌλ©΄ μ’μ κ²μ
λλ€... μλ₯Ό λ€μ΄ on_revoke() λλ on_abort() λ©μλλ₯Ό μ€λ²λ‘λν©λλ€. κ·Έλ¦¬κ³ μΌλΆ 쑰건μ λ°λΌ μ·¨μ μ μ¬λ¬ λμμ νλ λ°©λ²μΌ μλ μμ΅λλ€.
λ΄ 2 μΌνΈ, λλ μμ§ μ
λ¬λ¦¬ v4.0μ νμΈνμ§ μμμ΅λλ€.
μ΄κ²μ λν μ΄λ€ μ λ°μ΄νΈ?
κ°μ₯ μ μ©ν λκΈ
κ°μ¬ ν΄μ !
μμ μ μ’ λ£ μ μ€ν μ€μΈ μμ μ μ·¨μν μ μμμ΅λλ€. :
λ¨Όμ reserved_requests λͺ©λ‘μμ μμ μ μ·¨μνμ¬ κΈ°λ³Έμ μΌλ‘ μ’ λ£ μ§μ μ λκΈ° μ€μΈ μμ μ΄ μΈκ³λλ κ²μ λ°©μ§ν©λλ€.
κ·Έλ° λ€μ νμ± μμ²μ μ·¨μνκ³ μμ μμ μ 리 λμμ νΈλ¦¬κ±°ν μ μλλ‘ μμ μμ SoftTimeLimitExceeded μμΈλ₯Ό νΈλ¦¬κ±°ν©λλ€. acks_late(ν λ²μ νλμ μμ λ§ μ€ννκΈ° μν΄)λ₯Ό μ¬μ©νκ³ μμΌλ―λ‘ μμ μ μ¬λ°λ₯΄κ² μΉμΈνκ³ λ€μμ μμ μλ₯Ό μμν λ λ€μ μμνμ§ μλλ‘ μμ μμ 볡κ·νκ±°λ λ°μμμΌμΌ ν©λλ€.
μ€λ¨ κ°λ₯ν μμ μ μ¬μ©νκ³ μμ§λ§ μ€λ¨ λμμ μ¬μ©μκ° μλμ μΌλ‘ μμ μ μ€λ¨νκ³ μμ€ν μμ μΌλΆ 볡μ‘/κΈ΄ μ 리λ₯Ό μνν΄μΌ ν λ μ½λ©λ©λλ€. μ΄ κ²½μ°λ μμ μκ° μ’ λ£λλ κ²κ³Ό κ°μΌλ©°, μ΄ κ²½μ° νμ¬ μμ μ 빨리 μ€ν¨νκ² λ§λ€κ³ μΆμ΅λλ€.
λλ μ΄κ²μ΄ μλ¬λ¦¬μμ μΌμ νλ μ μ ν λ°©λ²μ΄λΌκ³ μκ°ν©λκΉ?
ν₯ν λ²μ μμλ Task ν΄λμ€μμ λμμ κ°λ¨ν μ¬μ μν μ μμΌλ©΄ μ’μ κ²μ λλ€... μλ₯Ό λ€μ΄ on_revoke() λλ on_abort() λ©μλλ₯Ό μ€λ²λ‘λν©λλ€. κ·Έλ¦¬κ³ μΌλΆ 쑰건μ λ°λΌ μ·¨μ μ μ¬λ¬ λμμ νλ λ°©λ²μΌ μλ μμ΅λλ€.
λ΄ 2 μΌνΈ, λλ μμ§ μ λ¬λ¦¬ v4.0μ νμΈνμ§ μμμ΅λλ€.