在 Django 中使用 Celery 來進行耗時操作
最近在實驗室中做一個專案(心酸啊,本想安安靜靜的清清閒閒的畢業的,沒想到。。。),要把實驗室發過的論文中的一些演算法整合到一個 Web 伺服器上,使用者可以上傳資料,還可以在 Web 上看到計算結果的視覺化圖表。整個伺服器的後臺是使用 Django 框架來搭建的,這些演算法需要處理一定量的資料,使用了 numpy,pandas,scipy 等數值計算庫,每一組資料的處理有時候需要跑好幾個小時。為了合理的排程這些演算法,我們這裡使用了 Celery。
1. Django 處理 Request 的基本流程
上面的這一張是網路上的 Django 處理 request 的流程示意圖。大致意思就是:
瀏覽器發起 http 請求 ----> http handling(request 解析) ----> url 匹配(正則匹配找到對應的 View) ----> 在View中進行邏輯的處理與資料計算(包括呼叫 Model 類進行資料庫的增刪改查)----> 將資料推送到 template,返回對應的 template/response。
對於一些簡單的操作,可以放在 View 中處理。在View處理任務時使用者處於等待狀態,直到頁面返回結果。但是對於一些複雜的操作,則在 View 中應該先返回 response,再在後臺處理任務。使用者無需等待。當任務處理完成時,我們可以再通過 Ajax 之類的方式告知使用者。
Celery 就是基於 Python 開發的一個分散式任務佇列框架,支援使用任務佇列的方式在分佈的機器/程式/執行緒上執行任務排程。
2. Celery
上圖是 Celery 的基本架構,它採用典型的生產生--消費者模式,主要由三部分組成:broker(訊息佇列)、workers(消費者:處理任務)、backend(儲存結果)。實際應用中,使用者從 Web 前端發起一個請求,我們只需要將請求所要處理的任務丟入任務佇列 broker 中,由空閒的 worker 去處理任務即可,處理的結果會暫存在後臺資料庫 backend 中。我們可以在一臺機器或多臺機器上同時起多個 worker 程式來實現分散式地並行處理任務。
3. 安裝 Celery
安裝過程就是直接按照官網上的文件安裝即可。我這裡用的均是目前的最新穩定版。
- macOS Sierra 10.12.3
- Django 1.10
- Celery 4.0.2
在早前版本的 Celery 中,有一個專門供 Django 使用的 Celery 版本:django-celery。但是在現在 Celery 已經統一為一個版本,所以直接安裝原生的 Celery 即可:
pip install celery
Celery 推薦使用 RabbitMQ,Redis,Amazon SQS,Zookeeper,這幾個作為 broker,但是隻有前兩個支援在生產環境使用。下面的表格對比了幾種 broker。
Name | Status | Monitoring | Remote Control |
---|---|---|---|
RabbitMQ | Stable | Yes | Yes |
Redis | Stable | Yes | Yes |
Amazon SQS | Stable | No | No |
Zookeeper | Experimental | No | No |
我是使用 Redis 作為 broker 的。除了安裝 redis 之外,還應該安裝 redis 的 python 支援庫。
安裝 Redis:
brew install redis
安裝 redis 的 python 支援庫:
pip install redis
輸入 redis-server
來開啟 redis。當你看見下面的圖案時,就說明成功開啟了 redis。redis 預設監聽 6379 埠。開啟之後可以用 ctrl+c 來退出。
4. 把 Celery 配置到 Django 上
假設你有一個專案 proj:
- proj/
- proj/__init__.py
- proj/settings.py
- proj/urls.py
- manage.py
Celery 建議在 proj/proj/celery.py
上定義一個 Celery 的例項。
檔案 proj/proj/celery.py:
from __future__ import absolute_import, unicode_literals
import os
from celery import Celery
# set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'proj.settings')
app = Celery('proj')
# 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()
@app.task(bind=True)
def debug_task(self):
print('Request: {0!r}'.format(self.request))
然後再在proj/proj/__init__.py
做一些配置。
檔案 proj/proj/__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 proj -l info
正常情況下,應該會出現類似於下圖的輸出。
ok,接下來,為了讓 celery 中執行的任務的結果返回我們的 Django,我們還應該安裝 django-celery-results
。
pip install django-celery-results
再在 proj/proj/settings.py:
中做如下的設定:
檔案proj/proj/settings.py:
# Celery 設定
CELERY_BROKER_URL = 'redis://localhost:6379/0'
CELERY_ACCEPT_CONTENT = ['json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_BACKEND = 'django-db'
CELERY_TIMEZONE = 'Asia/Shanghai'
INSTALLED_APPS = [
...
...
'django_celery_results'
]
再 migrate 一下:
migrate django_celery_results
5. 加入一個耗時任務
在你的 app 的目錄下,新建一個 tasks.py
檔案。在裡面加入一個耗時的任務:
from __future__ import absolute_import, unicode_literals
from celery import shared_task
# 模擬一個耗時操作
@shared_task
def longtime_test():
...
# 在這裡進行一些耗時操作
...
在 views.py
中,寫成這樣:
def test_view(request):
# do something
longtime_test.delay()
return render(request, 'template.html', {'data': data})
這樣之後,就會先返回 html 模版,再在後臺計算資料了。
相關文章
- 在django中使用celeryDjango
- celery 在django專案中使用Django
- Django 進階之 celeryDjango
- django中使用celeryDjango
- 使用go在mongodb中進行CRUD操作MongoDB
- Django專案中使用CeleryDjango
- Celery 進階使用
- celery4+django2定時任務Django
- Django配置celery執行非同步任務和定時任務Django非同步
- Python--Django:傳送郵箱 | 利用celery進行非同步處理PythonDjango非同步
- Django 如何使用 Celery 完成非同步任務或定時任務Django非同步
- Django Celery初識Django
- 求助!!!!Django+Celery非同步執行神經網路時出錯Django非同步神經網路
- 6.DJango在views裡面對獲取資料進行操作DjangoView
- django_celery_beat的部署Django
- python django與celery的整合PythonDjango
- 使用 iotop 監控哪些程式在進行I/O操作
- Python後端日常操作之在Django中「強行」使用MVVM設計模式Python後端DjangoMVVM設計模式
- Celery非同步排程框架(二)與Django結合使用非同步框架Django
- django + redis + celery 非同步任務DjangoRedis非同步
- 在Linux中,如何使用Suricata進行實時網路威脅檢測?Linux
- 如何在Django ORM中進行not查詢?DjangoORM
- 在PHP中進行curl開啟操作的具體教程PHP
- 在vue專案中 使用driver.js來進行頁面分步引導VueJS
- 在vue中使用ajax原聲程式碼進行匯出操作Vue
- django不使用序列化器來進行查詢結果序列化Django
- Django中views資料查詢使用locals()函式進行優化DjangoView函式優化
- 使用Instrument中的time profiler檢測耗時函式函式
- JPA之使用JPQL進行CRUD操作
- 在K8S中,在服務上線的時候Pod起不來怎麼進行排查?K8S
- Django+Celery非同步傳送郵件Django非同步
- 有序列表和集合插入操作的耗時差距
- Springboot:高併發下耗時操作的實現Spring Boot
- celery筆記八之資料庫操作定時任務筆記資料庫
- 在 Flask 專案中使用 Celery(with 工廠模式 or not)Flask模式
- 在django如何使用中文Django
- 走進新時代:在化工行業的變革中與時俱進開創未來行業
- 使用新操作碼在比特幣現金上進行首次原子競猜比特幣
- 使用dwebsocket在Django中使用WebsocketWebDjango