Vì vậy, hôm nay, tôi sẽ nói về một giải pháp thay thế Celery có tên Huey , đi kèm với thiết lập dễ dàng hơn nhiều so với Celery và có kích thước nhỏ hơn nhiều so với Celery.
Lý do tại sao tôi quyết định dùng thử Huey là vì đôi khi tôi gặp phải một số vấn đề với Celery khi thực hiện một số tác vụ thông thường vì tài liệu không quá nhiều.
Đối với những người chưa biết Celery là gì hoặc chưa từng sử dụng nó trước đây, Huey là hàng đợi tác vụ không đồng bộ cho phép bạn thực hiện các tác vụ theo lịch trình hoặc các tác vụ chạy trong nền.
Chúng ta sẽ cài đặt các gói sau:
Blog sau đây đi kèm với kho lưu trữ GitHub mà bạn có thể sử dụng để thử nghiệm dự án demo mà chúng tôi sẽ tạo.
Mở terminal và gõ thông tin sau để tạo một thư mục; bạn có thể bỏ qua bước này và thực hiện nó từ chính File Explorer.
mkdir huey_demo
Trước tiên, chúng ta hãy tạo một virtualenv để cài đặt các phụ thuộc dự án của mình:
python -m venv venv
Kích hoạt virtualenv (Linux):
source venv/bin/activate
Nhập lệnh sau vào terminal để cài đặt tất cả các phụ thuộc:
pip install Django==4.0.4 redis==4.2.2 huey==2.4.3
Tại thời điểm viết bài này, đây là những phiên bản tôi đã thử nghiệm thiết lập này, hãy theo dõi Github Repo để biết mọi bản cập nhật theo phiên bản mới nhất trong tương lai.
Tạo dự án Django bằng cách gõ lệnh sau trong terminal:
django-admin startproject django_huey_demo
Thay đổi thư mục vào thư mục dự án Django:
cd django_huey_demo
Tạo ứng dụng theo dự án của chúng tôi:
python manage.py startapp demo
Bao gồm ứng dụng đã tạo trong dự án settings.py
, thực hiện các thay đổi sau:
INSTALLED_APPS = [ # Existing Apps "demo.apps.DemoConfig", # <== Add this line ]
Đặt chế độ gỡ lỗi thành False
trong settings.py
:
DEBUG=False
Chúng tôi đang đặt Gỡ lỗi thành Sai để có thể xem Huey chạy như thế nào trong sản xuất, sau này sẽ nói thêm về điều này.
Bây giờ chúng ta đã hoàn tất việc thiết lập dự án của mình, đây là thời điểm thích hợp để giới thiệu cho bạn những gì chúng ta sẽ xây dựng ngày hôm nay.
Chúng tôi sẽ tìm nạp "Lời của ngày" hàng ngày từ API Wordnik . Sau đó, chúng tôi sẽ lưu trữ từ đó, định nghĩa của nó và ví dụ về từ đó trong câu trong cơ sở dữ liệu của chúng tôi.
Chúng tôi sẽ thiết lập một tác vụ định kỳ bằng cách sử dụng Huey để lấy Lời trong ngày và lưu trữ nó.
Để lưu trữ từ, chúng tôi sẽ tạo một Mô hình Django tương tự.
Bạn có thể làm theo hướng dẫn này để lấy khóa API.
Chúng tôi cần thêm Huey vào các ứng dụng đã cài đặt trong dự án của mình, vì vậy hãy thực hiện các thay đổi sau trong tệp settings.py
:
INSTALLED_APPS = [ # Existing apps 'huey.contrib.djhuey', # <== Add this line ]
Chúng ta cần cài đặt Redis cho Huey để lưu trữ thông tin về các tác vụ được xếp hàng đợi trong đó giống như chúng ta đã từng làm với Celery. Bạn có thể tham khảo liên kết sau để cài đặt Redis dựa trên hệ điều hành cụ thể của bạn.
Nếu bạn cảm thấy thoải mái khi sử dụng Docker, bạn có thể sử dụng lệnh sau:
docker run --name redis_huey -p 6379:6379 -d redis
Theo mặc định, Huey sẽ thử kết nối với máy chủ Redis đang chạy trên localhost:6379
. Nếu nó không có mặt, nó sẽ báo lỗi.
Thêm mã sau vào tệp demo/models.py
của bạn:
from django.db import models class Word(models.Model): word = models.CharField(max_length=200) part_of_speech = models.CharField(max_length=100) definition = models.TextField() example = models.TextField() def __str__(self): return self.word
Thực hiện di chuyển:
python manage.py makemigrations demo
Áp dụng di chuyển:
python manage.py migrate demo
Tạo một tệp có tên tasks.py
trong thư mục ứng dụng demo. Lý do chúng tôi đặt tên tệp của mình là tasks.py
là để giúp Huey tự động khám phá các tác vụ có trong ứng dụng đã đăng ký của chúng tôi, nếu chúng tôi đặt tên tệp của mình khác với tên đó, chúng tôi sẽ phải đăng ký tác vụ của mình theo cách thủ công. Nếu bạn muốn biết thêm, bạn có thể xem tài liệu của Huey tại đây .
Trước khi viết định nghĩa tác vụ, chúng ta cần cài đặt thêm một requests
phụ thuộc. Cài đặt nó bằng cách gõ dòng sau vào terminal của bạn:
pip install requests==2.27.1
Bây giờ, có mã:
import requests from django.conf import settings from huey import crontab from huey.contrib.djhuey import db_periodic_task from demo.models import Word @db_periodic_task(crontab(hour="18", minute="00")) def fetch_daily_word(): r = requests.get( f"https://api.wordnik.com/v4/words.json/wordOfTheDay?api_key={settings.WORDNIK_API_KEY}") data = r.json() Word.objects.get_or_create( word=data["word"], part_of_speech=data["definitions"][0]["partOfSpeech"], definition=data["definitions"][0]["text"], example=data["examples"][0]["text"] )
Thêm dòng sau vào cài đặt dự án của bạn:
WORDNIK_API_KEY = "api-key-here"
Khối mã này có thể có rất nhiều thứ cần sử dụng, vì vậy chúng ta hãy xem xét từng thứ một trong đó:
Trang trí Huey
from huey.contrib.djhuey import db_periodic_task
Đây là một trình trang trí do Huey cung cấp để đăng ký các tác vụ định kỳ liên quan đến làm việc với cơ sở dữ liệu, trình trang trí này tự động đóng kết nối cơ sở dữ liệu khi hoàn thành tác vụ, để biết thêm chi tiết, bạn có thể tham khảo tại đây.
Lịch trình Crontab
@db_periodic_task(crontab(hour="18", minute="00"))
Chúng tôi đang chuyển đối số crontab(hour="18", minute="00")
cho trình trang trí nhiệm vụ định kỳ của mình, điều này yêu cầu Huey chạy nhiệm vụ của chúng tôi vào lúc 6 giờ chiều hàng ngày. Bạn có thể sử dụng trang web này để tạo lịch trình crontab của mình, tôi luôn sử dụng nó.
Khóa API Wordnik
from django.conf import settings # Usage ## settings.WORDNIK_API_KEY
from django.conf import settings
là cách tiêu chuẩn để nhập bất kỳ dữ liệu nào từ cài đặt dự án của chúng tôi, nó rất hữu ích trong trường hợp chúng tôi có nhiều tệp cài đặt được thiết lập cho các môi trường khác nhau để nó sẽ biết nên chọn tệp nào mà không cần phải lo lắng về Nó. Nó tìm ra tệp cài đặt nào chúng tôi đang sử dụng từ biến môi trường DJANGO_SETTINGS_MODULE
. Nhưng bạn không cần phải lo lắng về những chi tiết này.
Sau đó, chúng tôi sử dụng khóa trong lệnh gọi API Wordnik của mình.
Cuộc gọi API Wordnik
r = requests.get( f"https://api.wordnik.com/v4/words.json/wordOfTheDay?api_key={settings.WORDNIK_API_KEY}")
Ở đây, chúng tôi đang sử dụng mô-đun yêu cầu để thực hiện yêu cầu NHẬN tới API Wordnik trong khi chuyển Khóa API của chúng tôi để xác thực.
Lưu trữ từ trong cơ sở dữ liệu
data = r.json() Word.objects.get_or_create( word=data["word"], part_of_speech=data["definitions"][0]["partOfSpeech"], definition=data["definitions"][0]["text"], example=data["examples"][0]["text"] )
Sau khi phân tích cú pháp phản hồi API, chúng tôi sẽ lưu trữ định nghĩa từ trong cơ sở dữ liệu của mình. Chúng tôi đang sử dụng phương thức get_or_create
thay vì phương thức create
ở đây để không tạo nhiều bản sao của cùng một từ trong cơ sở dữ liệu của mình nếu từ đó được API Wordnik lặp lại.
Phản hồi API Wordnik
Đây là phản hồi của API Wordnik cho điểm cuối Word of the Day. Một số phần không liên quan của phản hồi đã bị cắt bớt nhằm mục đích ngắn gọn.
{ "word": "stolon", "definitions": [ { "source": "ahd-5", "text": "A long thin stem that usually grows horizontally along the ground and produces roots and shoots at widely spaced nodes, as in a strawberry plant.", "note": null, "partOfSpeech": "noun" }, // More definitions here... ], "publishDate": "2022-05-08T03:00:00.000Z", "examples": [ { "title": "4.1 Nursery establishment", "text": "A stolon is a stem that grows along the ground, producing at its nodes new plants with roots and upright stems.", // Additional data here... }, // More examples here... ], // Additional fields here... }
Bạn có thể khởi động nhân viên Huey bằng cách gõ lệnh sau vào terminal của mình:
python manage.py run_huey
Bạn có thể chuyển nhiều cờ cho lệnh trên, lệnh này sẽ thay đổi những gì được ghi vào bảng điều khiển, chẳng hạn như:
-v, --verbose
- ghi nhật ký chi tiết (bao gồm mức DEBUG)-q, --quiet
- ghi nhật ký tối thiểu-S, --simple
- định dạng ghi nhật ký đơn giản ("tin nhắn thời gian")
Để xem nhiều tùy chọn khác để ghi nhật ký, hãy xem tài liệu tại đây .
Huey đi kèm với nhiều trình trang trí tác vụ tùy thuộc vào thao tác bạn đang thực hiện trong tác vụ.
Tôi sẽ giải thích ngắn gọn những gì tất cả những điều đó làm dưới đây.
Đây là câu lệnh nhập cho tất cả các trang trí:
from huey.contrib.djhuey import task, periodic_task, db_task, db_periodic_task
task
: Một nhiệm vụ thường xuyên.periodic_task
: Khi bạn muốn chạy một tác vụ định kỳ theo lịch trình.db_task
: Khi bạn muốn thực hiện các thao tác DB trong tác vụ của mình.db_periodic_task
: Khi bạn muốn thực hiện các thao tác DB trong một tác vụ định kỳ.Hãy để tôi chỉ cho bạn một số ví dụ khác về cách bạn có thể sử dụng crontab để lên lịch cho các nhiệm vụ của mình.
crontab(minute='*/3')
sẽ lên lịch cho tác vụ chạy ba phút một lần.crontab(hour='*/3', minute='5')
sẽ tạo một tác vụ chạy 5 phút sau mỗi giờ thứ ba.crontab(minute='00', hour='10', month='*/2', day_of_week='*/5')
sẽ tạo một tác vụ chạy vào ngày thứ 5 hàng tuần, của mỗi tháng thứ 2 vào lúc 10:00. Ví dụ: bạn có tác vụ sau được xác định bên trong tasks.py
:
from huey.contrib.djhuey import task @task() def count(): for i in range(10): print(i)
Bây giờ, nếu bạn muốn gọi tác vụ này nhưng muốn nó chạy sau 5 giây, bạn có thể làm như sau:
count.schedule(delay=5)
Tham số độ delay
nhận giá trị tính bằng giây, vì vậy nếu bạn muốn nó thực thi sau 5 phút, hãy chỉ định 300 giây.
Giả sử bạn thêm logic sau vào tác vụ hiện tại của chúng ta:
@db_periodic_task(crontab(hour="18", minute="00"), retries=2) def fetch_daily_word(): r = requests.get( f"https://api.wordnik.com/v4/words.json/wordOfTheDay?api_key={settings.WORDNIK_API_KEY}") if r.status_code != 200: raise Exception("Unable to fetch data from Wordnik API") ## Add this logic else: data = r.json() Word.objects.get_or_create( word=data["word"], part_of_speech=data["definitions"][0]["partOfSpeech"], definition=data["definitions"][0]["text"], example=data["examples"][0]["text"] )
Vì vậy, chúng tôi đã thêm logic để kiểm tra mã trạng thái của phản hồi và nếu đó là giá trị khác 200, nó sẽ thử lại tác vụ đó tối đa 2 lần. Nhưng những lần thử lại này sẽ diễn ra mà không có bất kỳ khoảng cách thời gian nào giữa hai lần thử. Bây giờ, nếu bạn muốn trì hoãn nhiều lần thực hiện tác vụ này thì sao? Chúng ta có thể làm điều đó bằng cách chuyển đối số retry_delay
, nó chấp nhận các giá trị tính bằng giây.
@db_periodic_task(crontab(hour="18", minute="00"), retries=2, retry_delay=10)
Điều này sẽ gây ra độ trễ 10 giây giữa nhiều lần thử.
Huey đi kèm với cài đặt mặc định giúp làm việc với Huey trong quá trình phát triển ở Django dễ dàng hơn. Vì vậy, bất cứ khi nào bạn có DEBUG=True
trong tệp settings.py
của mình, các tác vụ sẽ được thực thi đồng bộ giống như các lệnh gọi hàm thông thường. Mục đích của việc này là để tránh chạy cả Redis và một quy trình tiêu dùng bổ sung trong khi phát triển hoặc chạy thử nghiệm. Bạn có thể đọc thêm về điều này ở đây .
Để làm điều này, chúng ta cần thêm dòng sau vào settings.py
:
HUEY = {}
Tuy nhiên, nếu bạn muốn ghi đè hành vi này, bạn có thể thêm cấu hình Huey sau:
HUEY = { "immediate": False }
Nếu bạn có cấu hình trên được đề cập trong settings.py
, trong khi có DEBUG=True
, Huey sẽ yêu cầu bạn thiết lập Redis và chạy Huey Worker bằng lệnh run_huey
.
Một số nhận xét về Huey so với Celery là:
run_huey
.