Ref:html
https://www.jianshu.com/p/6f8576a37a3e前端
https://blog.csdn.net/Demo_3/article/details/78119951python
https://blog.csdn.net/spur_man/article/details/79550917ajax
https://my.oschina.net/37Y37/blog/1920149redis
http://docs.jinkan.org/docs/celery/getting-started/next-steps.html數據庫
https://www.ctolib.com/topics-130539.html#django
當前的需求是:我用form從前端拿到了提交的數據,因爲須要處理一點時間(也許不少用戶同時提請求呢)雖然感受暫時想多了=.=json
若是處理時間過長,那麼一方面頁面可能會超時,另外一方面,用戶等待過久也是不合適的。因此如今但願,在用戶提交數據後,馬上就服務器
能收到一個回覆(好比說task ID),等到任務結束後,通知用戶,用這個ID就能夠獲取結果(固然能夠是服務器靠這個ID來輸出結果)。架構
我也考慮過用ajax直接部分刷新頁面,可是感受對於長時間的併發任務,可能不是很合適(看到的ajax例子都是很簡單的,不是很懂是否是不適合複雜的計算邏輯?)。總之,爲了之後的發展,仍是學一下水芹菜吧。
異步任務處理:例如給註冊用戶發送短消息或者確認郵件任務。
大型任務:執行時間較長的任務,例如視頻和圖片處理,添加水印和轉碼等,須要執行任務時間長。
定時執行的任務:支持任務的定時執行和設定時間執行。例如性能壓測定時執行。
pip install celery
爲了讓celery中執行任務的結果返回Django,再裝一個
sudo pip install django-celery-results
使用redis作broker和backend,安裝:
sudo apt-get install redis
sudo pip install redis
若是apt-get有錯誤,請用下面的命令
sudo apt-get install redis --fix-missing
開啓redis服務
redis-server
報錯
我就知道不會一路順風的:)
解決:1. 找到redis-server進程,kill
2. 接着發現redis-server進程仍然存在,殺不掉:)
因此使用中止服務的命令。必要的話要用sudo。
/etc/init.d/redis-server stop
而後再重啓redis-service便可
如今正式來寫Celery了。首先看一下目錄結構:
配置階段先改celery.py和__init__.py
# Celery.py from __future__ import absolute_import, unicode_literals import os from celery import Celery, platforms # set the default Django settings module for the 'celery' program. os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'probe.settings') app = Celery('probe') # Using a string here means the worker don't have to serialize # the configuration object to child processes. # - namespace='CELERY' means all celery-related configuration keys # should have a `CELERY_` prefix. app.config_from_object('django.conf:settings', namespace='CELERY') # Load task modules from all registered Django app configs. app.autodiscover_tasks() # Allow root user run celery platforms.C_FORCE_ROOT = True @app.task(bind=True) def debug_task(self): print('Request: {0!r}'.format(self.request))
__init__.py
from __future__ import absolute_import, unicode_literals # This will make sure the app is always imported when # Django starts so that shared_task will use this app. from .celery import app as celery_app __all__ = ['celery_app']
而後進入根目錄
celery worker -A probe -l info
你覺得這樣就能夠了?報錯:
這是由於咱們的水芹找不到redis啊:)因此要修改上面的celery.py
# redis是broker和backend app = Celery('probe', backend='redis', broker='redis://localhost')
如今來配置一下celery。上面的修改暫時取消,咱們統一在settings.py裏配置celery。
CELERY_BROKER_URL = 'redis://localhost:6379' CELERY_ACCEPT_CONTENT = ['json'] CELERY_TASK_SERIALIZER = 'json' CELERY_RESULT_BACKEND = 'redis' CELERY_TIMEZONE = 'Asia/Shanghai'
CELERYD_MAX_TASKS_PER_CHILD = '1'
# celery在長時間運行後可能出現內存泄漏,須要添加這個配置,表示每一個worker執行了多少個任務就死掉
# INSTALLED_APPS裏再添加一個'django_celery_results'
而後migrate一下變化
python manage.py migrate django_celery_results
如今來真正寫任務了:task.py
這個task.py在每一個app下都要有,並且名稱不能改變。
from __future__ import absolute_import, unicode_literals from celery import shared_task @shared_task def longtime_test(): # 在這裏寫操做
而後在views.py裏(我這裏是把design2.py和主頁design-post綁在一塊兒的,因此我寫到design2.py裏去)
longtime_test.delay()
補一刀:
在design2.py裏,我這麼寫(省略其餘)這裏只是簡單測試一下:
import task def design_post(request): ... if request.POST: result = task.longtime_test.delay(ctx['target_definition'], ctx['target_species']) while True: if result.ready(): print "celery fried!" break; ...
事實上我第一次遇到了報錯
當時寫的是from task import longtime_test
我改爲上面的寫法以後,重啓celery,就沒有報錯:celery正確輸出字符串(畢竟我只作了字符串鏈接啊攤手)
並且django後臺這裏也正確反饋了(黃色標識)紅色的是以前報錯狀態的顯示。由於longtime_test函數同樣返回了,因此仍是會跳出循環。
好了我如今要去寫業務代碼了,配置方面的任務暫時告一段落:)