3

私はDjangoCelery、およびRabbitMQを使用しています。メールを送信する簡単なタスクがあります。このタスクは機能しますが、非常に遅いです。

たとえば、私は 5000 通のメールを送信し、5000 通のメールはすべて通常どおり直接RabbitMQに送信されますが、メッセージ ブローカーに入ると、すべてのタスクを完了してクリアするのに約 30 分かかります。

Celery がなければ、これらの同じタスクは 5000 個のタスクすべてを処理するのに数分しかかかりません。

何か設定を忘れていませんか? 誰かが私の速度の問題を見つけてくれたらとても助かります.

task.py

class SendMessage(Task):
    name = "Sending SMS"
    max_retries = 10
    default_retry_delay = 3

    def run(self, message_id, gateway_id=None, **kwargs):
        logging.debug("About to send a message.")


        try:
            message = Message.objects.get(pk=message_id)
        except Exception as exc:
            raise SendMessage.retry(exc=exc)

        if not gateway_id:
            if hasattr(message.billee, 'sms_gateway'):
                gateway = message.billee.sms_gateway
            else:
                gateway = Gateway.objects.all()[0]
        else:
            gateway = Gateway.objects.get(pk=gateway_id)

        account = Account.objects.get(user=message.sender)
        if account._balance() >= message.length:
            response = gateway._send(message)

            if response.status == 'Sent':
                # Take credit from users account.
                transaction = Transaction(
                    account=account,
                    amount=- message.charge,

                )
                transaction.save()
                message.billed = True
                message.save()
        else:
            pass

設定.py

# Celery
BROKER_URL = 'amqp://admin:xxxxxx@xx.xxx.xxx.xxx:5672//'
CELERY_SEND_TASK_ERROR_EMAILS = True

アパッチ構成

<VirtualHost *:80>
ServerName www.domain.com

DocumentRoot /srv/project/domain


WSGIDaemonProcess domain.com processes=2 threads=15 display-name=%{GROUP}
WSGIProcessGroup domain.com

WSGIScriptAlias / /srv/project/domain/apache/django.wsgi
ErrorLog /srv/project/logs/error.log
</VirtualHost>

conf

# Name of nodes to start, here we have a single node
#CELERYD_NODES="w1"
# or we could have three nodes:
CELERYD_NODES="w1 w2 w3"

# Where to chdir at start.
CELERYD_CHDIR="/srv/project/domain"

# How to call "manage.py celeryd_multi"
CELERYD_MULTI="$CELERYD_CHDIR/manage.py celeryd_multi"

# How to call "manage.py celeryctl"
CELERYCTL="$CELERYD_CHDIR/manage.py celeryctl"

# Extra arguments to celeryd
CELERYD_OPTS="--time-limit=900 --concurrency=8"

# %n will be replaced with the nodename.
CELERYD_LOG_FILE="/srv/project/logs/celery/%n.log"
CELERYD_PID_FILE="/srv/project/celery/%n.pid"

# Workers should run as an unprivileged user.
CELERYD_USER="root"
CELERYD_GROUP="root"

# Name of the projects settings module.
export DJANGO_SETTINGS_MODULE="domain.settings"

# Celery Beat Settings.

# Where to chdir at start.
CELERYBEAT_CHDIR="/srv/project/domain"

# Path to celerybeat
CELERYBEAT="$CELERYBEAT_CHDIR/manage.py celerybeat"
4

1 に答える 1

9

1 秒あたり最大 2.78 タスク (30 分で 5000 タスク) を処理していますが、これはそれほど高くないことに同意できます。3 つのノードがそれぞれ 8 の同時実行性で実行されているため、24 のタスクを並行して処理できるはずです。

確認事項:

CELERYD_PREFETCH_MULTIPLIER- これはデフォルトで 4 に設定されていますが、短いタスクがたくさんある場合は、増やす価値があります。ブローカーからメッセージを取得する時間の影響を軽減しますが、タスクがワーカー間で均等に分散されなくなります。

DB 接続/クエリ - 成功したケースで実行されている 5 つ以上の DB クエリを数えます。django-celery のデフォルトの結果バックエンドを使用している場合、タスク結果を DB に保存するための追加のクエリがあります。django-celery は、各タスクの後に DB 接続を閉じて再度開くため、オーバーヘッドが追加されます。5 つのクエリがあり、それぞれが 100 ミリ秒かかる場合、セロリの有無にかかわらず、タスクには少なくとも 500 ミリ秒かかります。クエリを単独で実行することは 1 つのことですが、他のタスクが効率的に並行して実行されるのを妨げているテーブル/行をタスク内でロックしているものがないことを確認する必要もあります。

ゲートウェイの応答時間 - あなたのタスクは、SMS ゲートウェイであると想定しているリモート サービスを呼び出しているようです。そのサーバーの応答が遅い場合、タスクは遅くなります。繰り返しますが、応答時間は、単一の呼び出しとピーク負荷でこれを行っている場合とで異なる場合があります。米国では、ロングコード SMS は 1 秒あたり 1 つのレートでしか送信できず、ゲートウェイがそのレート制限を行っている場所によっては、タスクが遅くなる可能性があります.

于 2013-08-20T17:06:34.020 に答える