文章

Django - 高效的後台任務調度與異步操作

現代 Web 應用常需要執行耗時或非即時的任務,例如發送郵件、處理大型數據、或與外部 API 交互。學習如何實現後台任務調度與異步操作,可以顯著提高應用的性能和用戶體驗。


課程目標

  1. 瞭解後台任務調度的必要性與常見工具。
  2. 學會使用 Celery 設計並執行異步任務。
  3. 探索 Django 與 asyncio 的結合,實現高效的異步操作。
  4. 使用 Redis 作為任務隊列的消息代理。

課程內容

1. 後台任務調度的應用場景

  • 發送郵件通知:用戶註冊或購物後的郵件回執。
  • 數據處理:如圖片壓縮或分析數據。
  • 定時任務:例如每天生成報表或清理過期數據。
  • 與外部 API 的長時間交互:如支付請求或數據同步。

2. 使用 Celery 設計後台任務

步驟 1:安裝 Celery 和 Redis

1
pip install celery[redis]

步驟 2:配置 Celery

在 Django 專案的根目錄創建 celery.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from __future__ import absolute_import, unicode_literals
import os
from celery import Celery

# 設置 Django 的默認設定
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project.settings')

app = Celery('project')

# 從 Django 的 settings.py 中加載設定
app.config_from_object('django.conf:settings', namespace='CELERY')

# 自動發現項目中的任務模組
app.autodiscover_tasks()

settings.py 中添加:

1
2
3
CELERY_BROKER_URL = 'redis://localhost:6379/0'  # 使用 Redis 作為消息代理
CELERY_ACCEPT_CONTENT = ['json']  # 支持的數據序列化格式
CELERY_TASK_SERIALIZER = 'json'   # 使用 JSON 進行序列化

__init__.py 中初始化:

1
2
3
4
5
6
from __future__ import absolute_import, unicode_literals

# 為 Django 應用程序導入 Celery
from .celery import app as celery_app

__all__ = ('celery_app',)

步驟 3:定義任務

在應用目錄(如 blog)的 tasks.py 中:

1
2
3
4
5
6
7
from celery import shared_task

@shared_task
def send_email_task(to_email):
    # 假設此處進行郵件發送
    print(f"Sending email to {to_email}")
    return f"Email sent to {to_email}"

步驟 4:調用任務

在視圖中調用異步任務:

1
2
3
4
5
from .tasks import send_email_task

def send_email_view(request):
    send_email_task.delay('user@example.com')  # 使用 delay() 執行任務
    return HttpResponse("Email task started!")

3. 配置定時任務

步驟 1:安裝定時器

使用 Celery 與 Django-Crontab 或 Celery-Beat 配合實現定時任務:

1
pip install django-celery-beat

步驟 2:配置 Celery-Beat

settings.py 中添加:

1
INSTALLED_APPS += ['django_celery_beat']

運行遷移:

1
python manage.py migrate

在管理後台中新增定時任務。


4. 使用 asyncio 實現異步操作

Django 自 3.1 起支持原生異步視圖,這對於處理高並發請求非常有用。

步驟 1:設計異步視圖

1
2
3
4
5
6
import asyncio
from django.http import JsonResponse

async def async_view(request):
    await asyncio.sleep(2)  # 模擬耗時操作
    return JsonResponse({'message': 'This is an async response!'})

步驟 2:與異步函數結合

使用 aiohttp 調用外部 API:

1
2
3
4
5
6
7
8
9
10
import aiohttp

async def fetch_data(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            return await response.json()

async def async_api_view(request):
    data = await fetch_data('https://api.example.com/data')
    return JsonResponse(data)

5. 監控與調試

Celery 任務監控工具

  • Flower:一個用於監控和管理 Celery 任務的 Web 工具。
1
2
pip install flower
celery -A project flower

訪問:http://localhost:5555

異步調試工具

  • 使用 printlogging 來記錄異步任務執行流程。
  • asyncio 中調用 loop.set_debug(True) 開啟調試模式。

課堂練習

  1. 使用 Celery 為 Blog 系統新增評論審核功能。
  2. 設計一個定時任務,每天清理未驗證用戶。
  3. 編寫一個異步視圖,實現與外部天氣 API 的交互並顯示天氣資訊。

作業

  1. 配置 Flower 監控工具,並測試任務執行情況。
  2. 修改 Blog 系統,使發送郵件功能使用 Celery 異步執行。
  3. 為系統新增一個每日生成報表的定時任務,並將結果保存到資料庫中。

本文章以 CC BY 4.0 授權