在這篇教學文章中,我將示範如何從零開始初始化一個 Django 專案,並且加入 Celery 進行異步任務處理,最後使用 Zeabur 將最後的完成品部署到 AWS 雲端伺服器。
Python Celery 是一個分散式任務佇列(distributed task queue)的工具,它允許你在應用程式中異步執行任務,並且可以將這些任務分發到多個工作者節點中執行,進而實現並行處理和負載平衡。
為什麼需要 Celery 呢?因為在現代的應用程式開發中,有許多任務是耗時的或需要執行於背景中,例如寄送郵件、處理圖像、生成報告等等。若將這些任務直接放在主應用程式中執行,會阻塞主線程並降低應用程式的性能和響應速度。Celery 的出現解決了這個問題,它讓開發者可以將這些耗時的任務委託給 Celery 來執行,從而保證了主應用程式的順暢運行,同時也提高了應用程式的可擴展性和靈活性。
以下是一些 Celery 的使用場景:
-
非同步任務處理:例如在網站後端處理用戶上傳的文件,或是定期爬取網站數據等。
-
計算密集型任務:例如圖像處理、數據轉換、機器學習模型訓練等。透過 Celery,這些任務可以在後台進行,不影響用戶體驗。
-
集群任務分發:當應用程式需要處理大量任務時,可以將這些任務分發到多個節點上執行,從而提高處理速度和系統的容量。
-
定時任務調度:Celery 提供了方便的定時任務調度功能,可以設置定時執行某些任務,例如每天凌晨執行數據備份任務、每小時生成報告等。
為了簡化文章,我們今天的示範以「開發一個數學網站 mathsite
」為例子,然後在「計算機 calculator
」中建立一個「加法計算 add
」的非同步任務。
先別急著吐槽!雖然加法計算是一個超快就能完成的動作,但為了模擬他是一個耗時的任務,我們在程式碼加入 sleep 20
假裝這是一個需要花費 20 秒才能完成的任務 XD
創建專案及虛擬環境
首先我們先在電腦上建立一個資料夾:
mkdir mathsite cd mathsite
然後,為你的專案創建一個虛擬環境以隔離依賴。
python -m venv venv source venv/bin/activate # 對於 Windows,使用 `venv\Scripts\activate`
然後記得把虛擬環境加入到 .gitignore
檔案裡面:
.gitignore:
venv
安裝 Django 和 Celery
接下來,安裝 Django 和 Celery 以及 Redis(我們將使用 Redis 作為 Celery 的 broker)。
pip install django celery redis
創建 Django 專案
使用 Django 命令行工具創建一個新的 Django 專案。
django-admin startproject mathsite .
創建 Django 應用
創建一個新的 Django 應用,我們將在這個應用中添加 Celery 任務。
python manage.py startapp calculator
配置 Django 專案
將新的應用添加到 INSTALLED_APPS
中。
mathsite/settings.py:
INSTALLED_APPS = [ ... 'calculator', ]
配置 Celery
在你的 Django 專案目錄下創建一個名為 celery.py
的文件,並進行以下配置:
mathsite/celery.py:
from __future__ import absolute_import, unicode_literals import os from celery import Celery # 設置默認的 Django 設置模塊 os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mathsite.settings') # 創建 Celery 應用 app = Celery('mathsite') # 使用 Django 的設定文件作為配置源 app.config_from_object('django.conf:settings', namespace='CELERY') # 自動發現任務模塊 app.autodiscover_tasks()
在 mathsite/__init__.py
中,導入並初始化 Celery 應用:
mathsite/init.py:
from __future__ import absolute_import, unicode_literals # 導入 Celery 應用 from .celery import app as celery_app # 將 Celery 應用暴露為模塊層級變量 __all__ = ('celery_app',)
配置 Celery 設定
因為 Celery 需要搭配 Redis 資料庫使用,所以我們可以先在 Zeabur 上部署一個 Redis 服務。
先建立一個專案:
npx @zeabur/cli project create
地區選擇 AWS 日本機房:
? Select project region [Use arrows to move, type to filter]
DigitalOcean - sgp1 (Enterprise Customers Only) (Singapore)
Amazon Web Services - us-west-1 (California, United States)
Amazon Web Services - ap-east-1 (Hong Kong)
Amazon Web Services - eu-central-1 (Frankfurt, Germany)
> Amazon Web Services - ap-northeast-1 (Tokyo, Japan)
Huawei Cloud - cn-east-3 (Shanghai, China (Beta))
然後就可以看到專案建立成功的訊息了:
INFO Project pitids created
INFO Project context is set to <pitids>
建立成功後,就可以部署 Redis 服務了:
npx @zeabur/cli service deploy --template=PREBUILT --marketplace-code=redis ✔ Service Redis created 🚀 https://dash.zeabur.com/projects/664c576eb6c2f12719418f66/services/664c5773b6c2f12719418f69
建立完成後我們就可以查看 Redis 的連接參數了:
npx @zeabur/cli service instruction --name=Redis
你應該會看到下面的輸出:
Command to connect to your Redis: redis-cli -h hkg1.clusters.zeabur.com -p 32724 -a NDoiHx6j305w7qdvVMAbp89S4W12hmuJ
Redis Connection String: redis://:NDoiHx6j305w7qdvVMAbp89S4W12hmuJ@hkg1.clusters.zeabur.com:32724
Redis password: NDoiHx6j305w7qdvVMAbp89S4W12hmuJ
Redis host: hkg1.clusters.zeabur.com
Redis port: 32724
第二行就是我們的 Redis 連接參數啦~
在 Django 的 settings.py
中添加 Celery 設定,使用你線上的 Redis 服務作為 broker 和結果後端:
mathsite/settings.py:
# Celery 設定 CELERY_BROKER_URL = '<你的 Redis 連接參數>/0' CELERY_RESULT_BACKEND = '<你的 Redis 連接參數>/0' CELERY_ACCEPT_CONTENT = ['json'] CELERY_TASK_SERIALIZER = 'json' CELERY_RESULT_SERIALIZER = 'json' CELERY_TIMEZONE = 'UTC' CELERY_BROKER_CONNECTION_RETRY_ON_STARTUP = True
記得將 你的 Redis 連接參數
替換為你從 npx @zeabur/cli service instruction
指令拿回來的連線參數哦,後面加上 /0
代表 Redis 的預設資料庫。
創建 Celery 任務
在應用中創建一個名為 tasks.py
的文件,並添加計算兩個數字之和的示例任務。
calculator/tasks.py:
from celery import shared_task import time @shared_task def add(x, y): time.sleep(20) # 為了假裝這是一個耗時的任務,我們讓它睡 20 秒 return x + y
創建 View 來調用 Celery 任務並返回任務 ID
在 calculator/views.py
中創建一個 View 來調用 Celery 任務並返回任務 ID。
calculator/views.py:
from django.http import JsonResponse from calculator.tasks import add from celery.result import AsyncResult def add_view(request): x = int(request.GET.get('x', 0)) y = int(request.GET.get('y', 0)) task = add.delay(x, y) return JsonResponse({'task_id': task.id}) def task_status_view(request, task_id): task_result = AsyncResult(task_id) response = { 'task_id': task_id, 'status': task_result.status, 'result': task_result.result, } return JsonResponse(response)
10. 配置 URL
在 calculator/urls.py
中配置 URL 路由,指向剛才創建的 View。
calculator/urls.py:
from django.urls import path from . import views urlpatterns = [ path('add/', views.add_view, name='add_view'), path('status/<str:task_id>/', views.task_status_view, name='task_status_view'), ]
並在主項目的 urls.py
中包含應用的 URL。
mathsite/urls.py:
from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('', include('calculator.urls')), ]
本地測試
現在,我們已經基本上把專案都準備好了!在部署到 AWS 之前,我們先來測試一下功能呢是否正常運行:
啟動 Celery Worker
在專案目錄中啟動 Celery worker:
celery -A mathsite worker --loglevel=info
啟動 Django 開發伺服器
在專案目錄中啟動 Django 開發伺服器:
python manage.py runserver
測試
-
發送一個計算請求:
打開瀏覽器,訪問
http://localhost:8000/add/?x=8&y=4
,你應該會看到返回一個任務 ID,如下所示:{ "task_id": "fbe599bb-7cea-4544-8b9a-057e704991c3" }
-
檢查任務狀態:
打開瀏覽器,訪問
http://localhost:8000/status/some-task-id
,你應該會看到任務的狀態和結果,如下所示:{ "task_id": "fbe599bb-7cea-4544-8b9a-057e704991c3", "status": "PENDING", "result": null }
可以看到
PEDING
代表任務還在進行中,畢竟加法是一個需要花費 20 秒才能完成的任務 🤣如果我們等 20 秒再打開一次的話:
{ "task_id": "fbe599bb-7cea-4544-8b9a-057e704991c3", "status": "SUCCESS", "result": 12 }
就可以看到任務完成了,且
result
也是正確的4+8=12
!
這樣,你就完成了從零開始初始化 Django 專案並加入 Celery 的過程,並且可以在本地測試你的 Celery 任務。
部署到線上
完成了本地測試以後,現在我們可以開始把專案部署到雲端了~
導出套件列表
首先,記得先把套件列表導出:
pip freeze > requirements.txt
部署服務
接下來,我們需要把 Django 和 Celery 分別部署為兩個獨立運行的服務,一個叫做 django
服務,另一個叫做 celery
服務。
雖然這兩個服務的程式碼是相同的,但 celery
服務需要使用不一樣的啟動指令,所以我們可以在專案的根目錄加入一個 zbpack.celery.json
檔案:
zbpack.celery.json:
{ "start_command": "celery -A mathsite worker --loglevel=info" }
然後部署:
npx @zeabur/cli deploy --create --name=django
然後再部署一次:
npx @zeabur/cli deploy --create --name=celery
現在我們的專案裡面應該有 redis
, django
和 celery
三個服務了,我們也可以去 Zeabur 的 dashboard 檢查看看:
綁定網域
最後,幫 Django 綁定一個可以從外網訪問的網域:
npx @zeabur/cli domain create ? Select a service django ? Is this a generated domain? Yes ? The subdomain part of zeabur.app: django-celery INFO Domain django-celery.zeabur.app added
這樣就綁定好了,注意不要綁定到錯誤的服務上喔,必須把域名綁定在 Django 服務否則是打不開的。
不過我們如果打開剛剛綁定的網域,你可能會看到這個錯誤頁面:
這是因為我們沒有把剛剛綁定的網域加入到 Django 的 ALLOWED_HOSTS
中,所以我們只要修改一下 mathsite/settings.py
裡面的內容,把
ALLOWED_HOSTS = []
改成
ALLOWED_HOSTS = ["django-celery.zeabur.app"]
然後重新部署一次(記得不要選錯服務,要選 django
哦):
npx @zeabur/cli deploy
就部署好了~
線上環境測試
這次,我們可以改用 curl
的方式進行線上環境的測試:
curl "https://django-celery.zeabur.app/add/?x=88&y=77" { "task_id": "a86a0914-42db-47f2-88b0-53a3a8b09cb0" }
任務啟動以後,等 20 秒再取得結果:
curl "https://django-celery.zeabur.app/status/a86a0914-42db-47f2-88b0-53a3a8b09cb0/" { "task_id": "a86a0914-42db-47f2-88b0-53a3a8b09cb0", "status": "SUCCESS", "result": 165 }
結語
這篇文章演示了如何從頭開始初始化一個 Django 專案,並添加 Celery 進行異步任務處理,最後使用 Zeabur 部署到 AWS 雲端伺服器上。我們從建立專案、安裝必要的套件,到配置 Celery、創建任務和 View,再到本地測試和線上部署,一步步地帶大家完成了整個流程。
透過這篇文章,不僅可以學到如何使用 Celery 來處理耗時的任務,從而提高應用程式的性能和響應速度。同時,通過部署到雲端伺服器上,讀者還可以學到如何使用 Zeabur 平台來輔助部署和管理應用程式,使整個開發過程更加順利和高效。
希望這篇文章能夠幫助到同學們更好地理解 Django 和 Celery 的使用,並且學會如何將自己的應用程式部署到線上環境中。如果這篇文章有幫助到你,可以在下面幫我按個愛心,以及留言告訴我你的想法。
如果你在跟著教學操作的途中遇到的任何問題,或是沒辦法順利的部署到 AWS 雲端,也歡迎來 Zeabur 的 Discord 頻道 找我喔!
有獎問卷調查
僅需要三分鐘,立即填寫 台灣開發者雲端部署習慣調查 問卷,幫助 Zeabur 改善使用者體驗,獲得價值 $150 台幣的免費雲端資源使用額度!