web-dev-qa-db-ja.com

Celery(Redis)結果のバックエンドが機能しない

Djangoを使用しているWebアプリケーションがあり、非同期タスクの処理にCeleryを使用しています。

Celeryでは、Rabbitmqをブローカーとして、Redisを結果のバックエンドとして使用しています。

RabbitmqとRedisは、ローカル仮想マシンでホストされている同じUbuntu 14.04サーバーで実行されています。

Celeryワーカーはリモートマシン(Windows 10)で実行されています(Djangoサーバー)で実行されているワーカーはありません)。

私には3つの問題があります(それらは何らかの形で関連していると思います!)。

  1. タスクが成功したか失敗したかに関係なく、タスクは「保留」状態のままです。
  2. 失敗したタスクは再試行しません。と私は再試行しようとするとこのエラーが表示されます:

reject requeue = False:[WinError 10061]ターゲットマシンがアクティブに拒否したため、接続できませんでした

  1. 結果のバックエンドが機能していないようです。

私も設定について混乱しており、この問題の原因がどこにあるのか正確にはわかりません!

これがこれまでの私の設定です:

my_app/settings.py

# region Celery Settings
CELERY_CONCURRENCY = 1
CELERY_ACCEPT_CONTENT = ['json']
# CELERY_RESULT_BACKEND = 'redis://:C@pV@[email protected]:6379/0'
BROKER_URL = 'amqp://soufiaane:C@pV@[email protected]:5672/cvcHost'
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TASK_SERIALIZER = 'json'
CELERY_ACKS_LATE = True
CELERYD_PREFETCH_MULTIPLIER = 1

CELERY_REDIS_Host = 'cvc.ma'
CELERY_REDIS_PORT = 6379
CELERY_REDIS_DB = 0
CELERY_RESULT_BACKEND = 'redis'
CELERY_RESULT_PASSWORD = "C@pV@lue2016"
REDIS_CONNECT_RETRY = True

AMQP_SERVER = "cvc.ma"
AMQP_PORT = 5672
AMQP_USER = "soufiaane"
AMQP_PASSWORD = "C@pV@lue2016"
AMQP_VHOST = "/cvcHost"
CELERYD_Hijack_ROOT_LOGGER = True
CELERY_Hijack_ROOT_LOGGER = True
CELERYBEAT_SCHEDULER = 'djcelery.schedulers.DatabaseScheduler'
# endregion

my_app/celery_settings.py

from __future__ import absolute_import
from Django.conf import settings
from celery import Celery
import Django
import os

# set the default Django settings module for the 'celery' program.
os.environ.setdefault('Django_SETTINGS_MODULE', 'my_app.settings')
Django.setup()
app = Celery('CapValue', broker='amqp://soufiaane:C@pV@[email protected]/cvcHost', backend='redis://:C@pV@[email protected]:6379/0')

# Using a string here means the worker will not have to
# pickle the object when using Windows.
app.config_from_object('Django.conf:settings')
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)


@app.task(bind=True)
def debug_task(self):
    print('Request: {0!r}'.format(self.request))

my_app__init__.py

from __future__ import absolute_import

# This will make sure the app is always imported when
# Django starts so that shared_task will use this app.

from .celery_settings import app as celery_app

my_app\email\tasks.py

from __future__ import absolute_import
from my_app.celery_settings import app

# here i only define the task skeleton because i'm executing this task on remote workers !
@app.task(name='email_task', bind=True, max_retries=3, default_retry_delay=1)
def email_task(self, job, email):
    try:
        print("x")
    except Exception as exc:
        self.retry(exc=exc)

ワーカー側には、タスクの実際の実装を含む1つのファイル「tasks.py」があります。

Worker\tasks.py

from __future__ import absolute_import
from celery.utils.log import get_task_logger
from celery import Celery


logger = get_task_logger(__name__)
app = Celery('CapValue', broker='amqp://soufiaane:C@pV@[email protected]/cvcHost', backend='redis://:C@pV@[email protected]:6379/0')

@app.task(name='email_task', bind=True, max_retries=3, default_retry_delay=1)
def email_task(self, job, email):
    try:
        """
        The actual implementation of the task
        """
    except Exception as exc:
        self.retry(exc=exc)

私が気づいたのは:

  • ワーカーのブローカー設定を不正なパスワードに変更すると、ブローカーに接続できませんでした。
  • ワーカーのバックエンド設定の結果を不正なパスワードに変更すると、すべてが正常であるかのように正常に実行されます。

これらの問題の原因は何ですか?

編集

redisサーバーで、リモート接続を既に有効にしている

/etc/redis/redis.conf

...バインド0.0.0.0 ...

20
Soufiaane

私の推測では、問題はパスワードにあります。パスワードに@が含まれています。これは、user:passHostセクションの間の仕切りとして解釈できます。

ブローカーに正しく接続できなかったため、ワーカーは保留状態のままです。セロリのドキュメントから http://docs.celeryproject.org/en/latest/userguide/tasks.html#pending

[〜#〜]保留中[〜#〜]タスクは実行を待機しているか、不明です。不明なタスクIDは保留状態にあることを意味します。

8
Gal Ben David

CELERY_STORE_ERRORS_EVEN_IF_IGNORED = Trueを設定に追加すると、この問題は解決しました。

1
Shaun Kruger

「単一インスタンスサーバー」(devサーバーとlocahostサーバー)が機能するように設定しましたが、redisサーバーが別のサーバーの場合は機能しませんでした。セロリタスクは正常に機能していましたが、結果が得られませんでした。タスクの結果を取得しようとしたときに、次のエラーが発生しました。

Error 111 connecting to localhost:6379. Connection refused.

それを機能させたのは、単にDjangoにその設定を追加することでした:

CELERY_RESULT_BACKEND = 'redis://10.10.10.10:6379/0'

このパラメーターが存在しない場合は、タスクの結果を取得するためにデフォルトでlocalhostになります。

0
mrmuggles