Django + Приложение Celery на Heroku работает локально, но рабочий тайм-аут при развертывании - PullRequest
0 голосов
/ 21 января 2020

У меня есть приложение 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!).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...