28

私には次のようなタスクがあります。

@task()
def async_work(info):
    ...

いつでも、私はいくつかの情報でasync_workを呼び出すかもしれません。何らかの理由で、一度に1つのasync_workのみが実行されていることを確認する必要があり、他の呼び出し要求は待機する必要があります。

だから私は次のコードを思い付く:

is_locked = False    
@task()
def async_work(info):
    while is_locked:
        pass
    is_locked = True
    ...
    is_locked = False

しかし、ローカル変数にアクセスすることは無効であると書かれています...それを解決するにはどうすればよいですか?

4

3 に答える 3

42

複数のセロリ ワーカーでタスクを実行できるため、ローカル変数へのアクセスは無効です。そして、それらのワーカーは異なるホスト上にある場合さえあります。したがって、基本的に、is_locked多くの Celery ワーカーがasync_workタスクを実行しているのと同じ数の変数インスタンスがあります。したがって、コードでエラーが発生しなくても、目的の効果は得られません。

目標を達成するには、1 つのワーカーのみを実行するように Celery を構成する必要があります。ワーカーはいつでも単一のタスクを処理できるため、必要なものを取得できます。

編集:

Workers Guide > Concurrencyによると:

デフォルトではマルチプロセッシングを使用してタスクの同時実行を実行しますが、Eventlet を使用することもできます。ワーカー プロセス/スレッドの数は、--concurrency引数を使用して変更できます。デフォルトは、マシンで使用可能な CPU の数です。

したがって、次のようにワーカーを実行する必要があります。

$ celery worker --concurrency=1

編集2:

驚いたことに、別の解決策があります。さらに、公式ドキュメントにもあります。タスクが一度に1つずつ実行されるようにするの記事を参照してください。

于 2012-08-17T09:34:56.967 に答える
15

おそらく、セロリ ワーカーには使用したくないでしょうconcurrency=1。タスクを同時に処理したいでしょう。代わりに、ある種のロック機構を使用できます。キャッシュのタイムアウトがタスクを完了する時間よりも大きいことを確認してください。

レディス

import redis
from contextlib import contextmanager

redis_client = redis.Redis(host='localhost', port=6378)


@contextmanager
def redis_lock(lock_name):
    """Yield 1 if specified lock_name is not already set in redis. Otherwise returns 0.

    Enables sort of lock functionality.
    """
    status = redis_client.set(lock_name, 'lock', nx=True)
    try:
        yield status
    finally:
        redis_client.delete(lock_name)


@task()
def async_work(info):
    with redis_lock('my_lock_name') as acquired:
        do_some_work()

Memcache

セロリのドキュメントに触発された例

from contextlib import contextmanager
from django.core.cache import cache

@contextmanager
def memcache_lock(lock_name):
    status = cache.add(lock_name, 'lock')
    try:
        yield status
    finally:
        cache.delete(lock_name)


@task()
def async_work(info):
    with memcache_lock('my_lock_name') as acquired:
        do_some_work() 
于 2019-02-11T08:00:04.273 に答える