2013-08-20 151 views
1

我正在使用Django,CeleryRabbitMQ。我有一個簡單的任務發送電子郵件。這項任務很有效,但速度很慢。慢芹菜任務時間

例如,我送5000電子郵件,所有5000個電子郵件直奔的RabbitMQ正常,但在消息中間件一次後,進入大約需要30分鐘才能完成並清除所有任務。

沒有芹菜這些相同的任務將需要幾分鐘時間來處理所有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 

settings.py

# Celery 
BROKER_URL = 'amqp://admin:[email protected]xxx.xxx.xxx:5672//' 
CELERY_SEND_TASK_ERROR_EMAILS = True 

Apache配置

<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" 
+0

有多少員工在完成任務? –

+0

@Mark Lavin 3名工人 – GrantU

+0

@Mark Lavin我已經添加了工人配置的東西供審查。 – GrantU

回答

6

您正在處理〜2.78個任務/秒(30分鐘內完成5000個任務),我可以同意的並不是那麼高。您有3個節點,每個節點的併發性爲8,因此您應該能夠並行處理24個任務。

檢查事項:

CELERYD_PREFETCH_MULTIPLIER - 這是默認設置爲4,但如果你有大量的短期任務,它可以是值得予以增加。它會減少從經紀人那裏收到消息的時間所帶來的影響,但代價是任務不會在工作人員中均勻分配。

數據庫連接/查詢 - 我計數5+ DB查詢正在執行的成功案例。如果您正在使用django-celery的默認結果後端,則會有額外的查詢將任務結果存儲在數據庫中。 django-celery在每次任務之後還會關閉並重新打開數據庫連接,這會增加一些開銷。如果你有5個查詢,每個需要100毫秒,那麼你的任務至少需要500毫秒,有無芹菜。自行運行查詢是一回事,但您還需要確保任務中沒有任何內容鎖定表/行,以防止其他任務並行高效運行。

網關響應時間 - 您的任務似乎調用遠程服務,我假設這是一個短信網關。如果該服務器響應緩慢,那麼你的任務將會很慢。對於單次呼叫,當您在峯值負載下進行此操作時,響應時間可能會不同。在美國,長碼SMS只能以每秒1次的速率發送,並且取決於網關正在進行速率限制的位置,因此可能會減慢您的任務速度。

+1

哇這真的很有幫助。你會介意告訴你如何從我的代碼中破解〜2.78個任務/秒(30分鐘內執行5000個任務),這是怎麼解決的?它真的會幫助我,謝謝。 – GrantU

+0

>所以你應該能夠並行處理24個任務---我應該嘗試更多的工人和更多的併發任務嗎?這會工作嗎? – GrantU

+1

30分鐘內5000個任務是您在問題主體中的主張,而不是我的主張。 –