У меня есть приложение Django + Celery, использующее RabbitMQ, которое прекрасно работает локально (при вызове heroku local
), но не выполняет задачи при развертывании. Кажется, что «рабочий тайм-аут» возникает каждый раз, когда вызывается задача. Версии компонентов: Django (3.0.1), сельдерей (4.4.0).
Журналы Heroku:
2020-01-21T15:38:48.828631+00:00 heroku[router]: at=error code=H12 desc="Request timeout" method=POST path="<REDACTED>" host=<REDACTED> request_id=c59b92be-9b39-4a36-a1d0-e646c9b1f694 fwd="<REDACTED> " dyno=web.1 connect=1ms service=30000ms status=503 bytes=0 protocol=https
2020-01-21T15:38:49.822330+00:00 app[web.1]: [2020-01-21 15:38:49 +0000] [4] [CRITICAL] WORKER TIMEOUT (pid:10)
2020-01-21T15:38:49.823866+00:00 app[web.1]: [2020-01-21 23:38:49 +0800] [10] [INFO] Worker exiting (pid: 10)
2020-01-21T15:38:49.982428+00:00 app[web.1]: [2020-01-21 15:38:49 +0000] [14] [INFO] Booting worker with pid: 14
Рабочий RabbitMQ согласно журналам, кажется, работает нормально:
2020-01-21T15:33:53.899791+00:00 app[worker.1]: [2020-01-21 23:33:53,899: INFO/MainProcess] mingle: searching for neighbors
2020-01-21T15:33:54.969851+00:00 app[worker.1]: [2020-01-21 23:33:54,969: INFO/MainProcess] mingle: all alone
2020-01-21T15:33:55.055792+00:00 app[worker.1]: [2020-01-21 23:33:55,055: INFO/MainProcess] celery@aaec950b-24bd-4d29-8c43-c8eeb71e58de ready.
Procfile:
web: gunicorn gotcha.wsgi --log-level debug
worker: celery -A gotcha worker -l info
Я пытался запустить простое задание (просто печатает строку) на Heroku с помощью команды heroku run python manage.py shell
, и это также казалось, бежать без остановки.
Задача:
@task()
def test():
print("test")
Принудительный выход приводит к следующей ошибке:
Traceback (most recent call last):
File "/app/.heroku/python/lib/python3.6/site-packages/kombu/utils/functional.py", line 43, in __call__
return self.__value__
AttributeError: 'ChannelPromise' object has no attribute '__value__'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/app/.heroku/python/lib/python3.6/site-packages/amqp/transport.py", line 137, in _connect
host, port, family, socket.SOCK_STREAM, SOL_TCP)
File "/app/.heroku/python/lib/python3.6/socket.py", line 745, in getaddrinfo
for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno -9] Address family for hostname not supported
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/app/.heroku/python/lib/python3.6/site-packages/kombu/utils/functional.py", line 344, in retry_over_time
return fun(*args, **kwargs)
File "/app/.heroku/python/lib/python3.6/site-packages/kombu/connection.py", line 283, in connect
return self.connection
File "/app/.heroku/python/lib/python3.6/site-packages/kombu/connection.py", line 839, in connection
self._connection = self._establish_connection()
File "/app/.heroku/python/lib/python3.6/site-packages/kombu/connection.py", line 794, in _establish_connection
conn = self.transport.establish_connection()
File "/app/.heroku/python/lib/python3.6/site-packages/kombu/transport/pyamqp.py", line 130, in establish_connection
conn.connect()
File "/app/.heroku/python/lib/python3.6/site-packages/amqp/connection.py", line 311, in connect
self.transport.connect()
File "/app/.heroku/python/lib/python3.6/site-packages/amqp/transport.py", line 77, in connect
self._connect(self.host, self.port, self.connect_timeout)
File "/app/.heroku/python/lib/python3.6/site-packages/amqp/transport.py", line 148, in _connect
"failed to resolve broker hostname"))
File "/app/.heroku/python/lib/python3.6/site-packages/amqp/transport.py", line 161, in _connect
self.sock.connect(sa)
ConnectionRefusedError: [Errno 111] Connection refused
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/app/.heroku/python/lib/python3.6/site-packages/celery/app/task.py", line 425, in delay
return self.apply_async(args, kwargs)
File "/app/.heroku/python/lib/python3.6/site-packages/celery/app/task.py", line 568, in apply_async
**options
File "/app/.heroku/python/lib/python3.6/site-packages/celery/app/base.py", line 771, in send_task
amqp.send_task_message(P, name, message, **options)
File "/app/.heroku/python/lib/python3.6/site-packages/celery/app/amqp.py", line 559, in send_task_message
**properties
File "/app/.heroku/python/lib/python3.6/site-packages/kombu/messaging.py", line 181, in publish
exchange_name, declare,
File "/app/.heroku/python/lib/python3.6/site-packages/kombu/connection.py", line 518, in _ensured
return fun(*args, **kwargs)
File "/app/.heroku/python/lib/python3.6/site-packages/kombu/messaging.py", line 187, in _publish
channel = self.channel
File "/app/.heroku/python/lib/python3.6/site-packages/kombu/messaging.py", line 209, in _get_channel
channel = self._channel = channel()
File "/app/.heroku/python/lib/python3.6/site-packages/kombu/utils/functional.py", line 45, in __call__
value = self.__value__ = self.__contract__()
File "/app/.heroku/python/lib/python3.6/site-packages/kombu/messaging.py", line 224, in <lambda>
channel = ChannelPromise(lambda: connection.default_channel)
File "/app/.heroku/python/lib/python3.6/site-packages/kombu/connection.py", line 868, in default_channel
self.ensure_connection(**conn_opts)
File "/app/.heroku/python/lib/python3.6/site-packages/kombu/connection.py", line 430, in ensure_connection
callback, timeout=timeout)
File "/app/.heroku/python/lib/python3.6/site-packages/kombu/utils/functional.py", line 358, in retry_over_time
sleep(1.0)
KeyboardInterrupt
EDIT 1: я использую надстройку CloudAMQP. Я попытался запустить heroku локально, но на этот раз с URL-адресом CloudAMQP, предоставленным дополнением. В первый раз, когда я его запустил, был рабочий тайм-аут, но в последующих попытках задачи просто не были получены. Таким образом, проблема связана с использованием CLoudAMQP . Я использую бесплатный уровень .
Как только я заменяю CELERY_BROKER_URL
на локально размещенный RabbitMQ, кажется, что все задачи получены:
12:13:32 PM worker.1 | [2020-01-22 12:13:32,021: INFO/MainProcess] Received task: accounts.tasks.send_targets_and_codes[fe363114-b058-4486-81ca-cb2bac6cc48c] ETA:[2020-01-22 12:01:00+08:00]
12:13:32 PM worker.1 | [2020-01-22 12:13:32,022: INFO/MainProcess] Received task: accounts.tasks.send_targets_and_codes[1de3aef0-bb10-41cf-b133-0cb3f2b2c34d] ETA:[2020-01-22 12:06:00+08:00]
12:13:32 PM worker.1 | [2020-01-22 12:13:32,023: INFO/MainProcess] Received task: accounts.tasks.send_targets_and_codes[9dd9631d-0bb3-468e-91c0-abfa83ab940e] ETA:[2020-01-22 12:16:00+08:00]
12:13:32 PM worker.1 | [2020-01-22 12:13:32,150: INFO/ForkPoolWorker-1] Task accounts.tasks.send_targets_and_codes[1de3aef0-bb10-41cf-b133-0cb3f2b2c34d] succeeded in 0.024096399996778928s: None
12:13:32 PM worker.1 | [2020-01-22 12:13:32,150: INFO/ForkPoolWorker-8] Task accounts.tasks.send_targets_and_codes[fe363114-b058-4486-81ca-cb2bac6cc48c] succeeded in 0.024374700005864725s: None
12:13:32 PM worker.1 | [2020-01-22 12:13:32,186: INFO/ForkPoolWorker-7] Task accounts.tasks.send_targets_and_codes[2c891064-17d8-479b-8849-682889d75d8b] succeeded in 0.06000789999961853s: None
РЕДАКТИРОВАТЬ 2: Оказывается, что если мой локальный сервер RabbitMQ работал, хотя я установил URL-адрес посредника на CloudAMQP, задачи все равно будут отправляться на локальный. Тем не менее, после отключения локального сервера, я получаю страшную
1:04:48 PM web.1 | [2020-01-22 13:04:48 +0800] [10964] [CRITICAL] WORKER TIMEOUT (pid:11003)
1:04:48 PM web.1 | [2020-01-22 13:04:48 +0800] [11003] [INFO] Worker exiting (pid: 11003)
1:04:48 PM web.1 | [2020-01-22 13:04:48 +0800] [11005] [INFO] Booting worker with pid: 11005
РЕДАКТИРОВАТЬ 3: Я пытался использовать локальный сервер Redis и возникает точно такая же ошибка WORKER TIMEOUT
. Работник, похоже, связан с Redis.
Вот очень необычная вещь, однако. Если также работает локальный сервер RabbitMQ, задачи будут приниматься этим сервером (поэтому ошибка WORKER TIMEOUT
не возникает). Это наводит меня на мысль, что что-то связано с тем, что Celery предварительно настроен только для RabbitMQ (и даже не для CloudAMQP!).