django + redis + celery 非同步任務

二月雪發表於2024-10-04

前言:

  • python version >= 3.6
  • 安裝並執行redis
  • 建立好個人的django專案
  • 安裝celery
# redis
pip install redis

# 安裝celery

pip install celery  # 用本地的python環境進行安裝,不要用anaconda的python安裝
pip install eventlet  # windows下還需要 安裝執行celery的第三方依賴
#幫助文件 多看看 
celery --help 
#常規啟動Worker 
celery -A dashboard worker -l info
#Windows下啟動Worker 
celery -A dashboard worker -l info -P eventlet
#關閉Worker 退出
Ctrl + C 
 

#啟動Beat程式 可以幫我們定時傳送任務到訊息佇列 
celery -A tasks beat --loglevel=INFO 

目錄結構

E:.
│  db.sqlite3
│  Dockerfile
│  manage.py
│  requirements.txt
│
├─celery_tasks  # 自定義一個celery的工作目錄
│  │  config.py  # celery配置檔案
│  │  __init__.py
│  │
│  ├─sms
│      tasks.py   #  worker任務
│      __init__.py
│    
│
├─dashboard
│  │  asgi.py
│  │  celery.py  # 同settings.py目錄下 建立該檔案
│  │  settings.py
│  │  urls.py
│  │  wsgi.py
│  │  __init__.py  # 修改該檔案
│
├─dbcv  # app
  │  admin.py
  │  apps.py
  │  models.py
  │  serializers.py
  │  test.py
  │  tests.py
  │  views.py
  │  __init__.py
......

django 建立celery + redis非同步任務

1、建立celery工作目錄
在專案根目錄下建立 celery_tasks

2、建立config.py配置檔案

# 配置非同步任務

# 設定結果儲存
result_backend = 'redis://127.0.0.1:6379/1'

# 設定代理人broker
broker_url = 'redis://127.0.0.1:6379/2'

# celery 的啟動工作數量設定
CELERY_WORKER_CONCURRENCY = 20
# 任務預取功能,就是每個工作的程序/執行緒在獲取任務的時候,會盡量多拿 n 個,以保證獲取的通訊成本可以壓縮。
WORKER_PREFETCH_MULTIPLIER = 20
# 非常重要,有些情況下可以防止死鎖
CELERYD_FORCE_EXECV = True
# celery 的 worker 執行多少個任務後進行重啟操作
CELERY_WORKER_MAX_TASKS_PER_CHILD = 100
# 禁用所有速度限制,如果網路資源有限,不建議開足馬力。
WORKER_DISABLE_RATE_LIMITS = True
# 明確指示在啟動時進行連線重試
# BROKER_CONNECTION_RETRY_ON_STARTUP = True
broker_connection_retry_on_startup = True

# 2、配置定時任務
timezone = 'Asia/Shanghai'
DJANGO_CELERY_BEAT_TZ_AWARE = False
CELERY_BEAT_SCHEDULER = 'django_celery_beat.schedulers:DatabaseScheduler'

2、建立celery.py

同settings.py目錄下 建立該檔案

import os

from django.utils import timezone
from celery import Celery
# from celery.schedules import crontab, timedelta

from celery_tasks import config

# 設定環境變數, 匯入django配置; 後續便於使用django元件功能
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'dashboard.settings')

app = Celery("apps")

# 讀取配置檔案中的配置
app.config_from_object(config)

# 自動從django註冊的app中發現所有任務
app.autodiscover_tasks()

# 解決時區問題,定時任務啟動就迴圈輸出
app.now = timezone.now

# celery -A dashboard worker -l info -P eventlet

3、建立個wocker檔案:tasks.py

常見的如傳送郵件、簡訊等等

# tasks.py

import time
from dashboard.celery import app


# 透過 @app.task 裝飾器,定義celery的wocker函式物件

@app.task
def send_sms(desc=None):
    print("send_sms start")
    if desc:
        print(desc)
    time.sleep(20)
    print("send_sms end")
    return "send_sms ok"

4、在app檢視中呼叫

@api_view(['GET'])
def test(request):
    """
    測試token
    """
    current_time = timezone.now()
    print("當前時間是:{}".format(current_time))

    # .delay() 方法呼叫
    result = tasks.send_sms.delay("檢視呼叫celery任務")

    res_data = {'data': {'status_code': 200}}
    return Response(**res_data)

5、執行celery
開啟終端,win+r,cmd

# windows下需要加 -P eventlet 執行,否則會報錯(celery的問題)
celery -A dashboard worker -l info -P eventlet

# Linux下
celery -A dashboard worker -l info

6、執行django

python manage.py runserver

7、透過介面呼叫介面API,觀察celery的執行即可

完成!!!

日常踩坑可參考:吐血總結,避坑指南

相關文章