그래서 오늘은 Huey 라는 Celery 대안에 대해 이야기하겠습니다. Huey는 Celery 보다 설정이 훨씬 쉽고 Celery에 비해 크기가 훨씬 작습니다.
내가 Huey를 사용하기로 결정한 이유는 문서가 너무 훌륭하지 않기 때문에 Celery에서 가끔 몇 가지 일반적인 작업을 수행하는 데 몇 가지 문제에 직면했기 때문입니다.
Celery가 무엇인지 모르거나 이전에 사용해 본 적이 없는 사람들을 위해 Huey는 예약된 작업이나 장기 실행 작업을 백그라운드에서 수행할 수 있는 비동기 작업 대기열입니다.
우리는 다음 패키지를 설치할 것입니다:
다음 블로그에는 우리가 만들 데모 프로젝트를 테스트하는 데 사용할 수 있는 GitHub 저장소가 함께 제공됩니다.
터미널을 열고 다음을 입력하여 디렉터리를 만듭니다. 이 단계를 건너뛰고 파일 탐색기 자체에서 수행할 수 있습니다.
mkdir huey_demo
프로젝트 종속성을 설치하기 위해 먼저 virtualenv를 생성해 보겠습니다.
python -m venv venv
virtualenv를 활성화합니다(Linux):
source venv/bin/activate
모든 종속성을 설치하려면 터미널에 다음 명령을 입력하십시오.
pip install Django==4.0.4 redis==4.2.2 huey==2.4.3
이 기사를 작성할 당시 이 설정을 테스트한 버전은 다음과 같습니다. 향후 최신 버전에 따른 업데이트가 있는지 Github Repo를 주시하세요.
터미널에 다음 명령을 입력하여 Django 프로젝트를 만듭니다.
django-admin startproject django_huey_demo
디렉터리를 Django 프로젝트 디렉터리로 변경합니다.
cd django_huey_demo
프로젝트 아래에 앱을 만듭니다.
python manage.py startapp demo
생성된 앱을 settings.py
프로젝트에 포함하고 다음과 같이 변경합니다.
INSTALLED_APPS = [ # Existing Apps "demo.apps.DemoConfig", # <== Add this line ]
settings.py
에서 디버그 모드를 False
로 설정합니다.
DEBUG=False
나중에 Huey가 프로덕션에서 어떻게 실행되는지 확인할 수 있도록 Debug를 False로 설정하고 있습니다.
이제 프로젝트 설정이 완료되었으므로 오늘 구축할 내용을 살펴보겠습니다.
Wordnik API 에서 매일 "오늘의 단어"를 가져옵니다. 그런 다음 데이터베이스에 단어, 정의, 문장에 포함된 단어의 예를 저장합니다.
Huey를 사용하여 오늘의 단어를 가져와서 저장하는 주기적 작업을 설정하겠습니다.
단어를 저장하기 위해 우리는 동일한 Django 모델을 생성할 것입니다.
이 가이드 에 따라 API 키를 얻을 수 있습니다.
프로젝트에 설치된 앱에 Huey를 추가해야 하므로 settings.py
파일을 다음과 같이 변경합니다.
INSTALLED_APPS = [ # Existing apps 'huey.contrib.djhuey', # <== Add this line ]
Celery에서 했던 것처럼 대기 중인 작업에 대한 정보를 저장하려면 Huey용 Redis를 설치해야 합니다. 특정 운영 체제에 따라 Redis를 설치하려면 다음 링크 를 참조할 수 있습니다.
Docker 사용에 익숙하다면 다음 명령을 사용할 수 있습니다.
docker run --name redis_huey -p 6379:6379 -d redis
기본적으로 Huey는 localhost:6379
에서 실행되는 Redis 서버에 연결을 시도합니다. 존재하지 않으면 오류가 발생합니다.
demo/models.py
파일에 다음 코드를 추가합니다.
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
마이그레이션을 수행합니다.
python manage.py makemigrations demo
마이그레이션 적용:
python manage.py migrate demo
데모 앱 디렉터리에 tasks.py
라는 파일을 만듭니다. 파일 이름을 tasks.py
로 지정한 이유는 Huey가 등록된 앱에 있는 작업을 자동으로 검색할 수 있도록 돕기 위한 것입니다. 파일 이름이 다른 이름으로 지정되면 작업을 수동으로 등록해야 합니다. 더 자세한 내용을 알고 싶으면 여기에서 Huey 문서를 확인하세요.
작업 정의를 작성하기 전에 추가 종속성 requests
설치해야 합니다. 터미널에 다음을 입력하여 설치하십시오.
pip install requests==2.27.1
이제 코드가 나옵니다:
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"] )
프로젝트 설정에 다음 줄을 추가하세요.
WORDNIK_API_KEY = "api-key-here"
이 코드 블록은 다루어야 할 내용이 많을 수 있으므로 그 내용을 하나씩 살펴보겠습니다.
휴이 데코레이터
from huey.contrib.djhuey import db_periodic_task
이는 데이터베이스 작업과 관련된 주기적 작업을 등록하기 위해 Huey에서 제공하는 데코레이터입니다. 이 데코레이터는 작업 완료 시 자동으로 데이터베이스 연결을 닫습니다. 자세한 내용은 여기를 참조하세요.
크론탭 일정
@db_periodic_task(crontab(hour="18", minute="00"))
crontab(hour="18", minute="00")
인수를 주기적 작업 데코레이터에 전달합니다. 이는 Huey에게 매일 오후 6시에 작업을 실행하라고 지시합니다. 이 웹사이트 를 활용하여 crontab 일정을 만들 수 있습니다. 저는 매번 이 웹사이트를 사용합니다.
Wordnik API 키
from django.conf import settings # Usage ## settings.WORDNIK_API_KEY
from django.conf import settings
프로젝트 설정에서 데이터를 가져오는 표준 방법입니다. 서로 다른 환경에 대해 여러 설정 파일이 설정된 경우에 유용하므로 걱정할 필요 없이 어떤 파일을 선택할지 알 수 있습니다. 그것. DJANGO_SETTINGS_MODULE
환경 변수에서 어떤 설정 파일을 사용하고 있는지 알아냅니다. 하지만 이러한 세부 사항에 대해 걱정할 필요가 없습니다.
그런 다음 Wordnik API 호출에서 키를 사용합니다.
Wordnik API 호출
r = requests.get( f"https://api.wordnik.com/v4/words.json/wordOfTheDay?api_key={settings.WORDNIK_API_KEY}")
여기서는 인증을 위해 API 키를 전달하는 동안 요청 모듈을 사용하여 Wordnik API에 대한 GET 요청을 만들고 있습니다.
데이터베이스에 단어 저장
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"] )
API 응답을 구문 분석한 후 데이터베이스에 단어 정의를 저장합니다. 여기서는 create
메소드 대신 get_or_create
메소드를 사용하여 해당 단어가 Wordnik API에 의해 반복되는 경우 데이터베이스에 동일한 단어의 여러 복사본을 생성하지 않습니다.
Wordnik API 응답
오늘의 단어 엔드포인트에 대한 Wordnik API 응답은 다음과 같습니다. 응답의 관련 없는 부분 중 일부는 간결성을 위해 잘렸습니다.
{ "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... }
터미널에 다음 명령을 입력하여 Huey 작업자를 시작할 수 있습니다.
python manage.py run_huey
위 명령에 다음과 같이 콘솔에 기록되는 내용을 변경하는 여러 플래그를 전달할 수 있습니다.
-v, --verbose
- 자세한 로깅(DEBUG 수준 포함)-q, --quiet
- 최소 로깅-S, --simple
- 간단한 로깅 형식(“시간 메시지”)
다양한 로깅 옵션을 보려면 여기 문서를 확인하세요.
Huey에는 작업 내에서 수행하는 작업에 따라 여러 작업 데코레이터가 제공됩니다.
아래에서 이들 모두가 수행하는 작업을 간략하게 설명하겠습니다.
모든 데코레이터에 대한 import 문은 다음과 같습니다.
from huey.contrib.djhuey import task, periodic_task, db_task, db_periodic_task
task
: 일반적인 작업입니다.periodic_task
: 일정에 따라 주기적으로 작업을 실행하려는 경우.db_task
: 작업 내에서 DB 작업을 수행하려는 경우.db_periodic_task
: 주기적인 작업으로 DB 작업을 수행하고 싶을 때.crontab을 사용하여 작업을 예약하는 방법에 대한 몇 가지 예를 더 보여드리겠습니다.
crontab(minute='*/3')
작업이 3분마다 실행되도록 예약합니다.crontab(hour='*/3', minute='5')
매 3시간마다 5분에 실행되는 작업을 생성합니다.crontab(minute='00', hour='10', month='*/2', day_of_week='*/5')
매 2개월마다 5일마다 실행되는 작업을 생성합니다. 오전 10시. 예를 들어, tasks.py
내부에 다음 작업이 정의되어 있습니다.
from huey.contrib.djhuey import task @task() def count(): for i in range(10): print(i)
이제 이 작업을 호출하고 5초 후에 실행되도록 하려면 다음을 수행하면 됩니다.
count.schedule(delay=5)
delay
매개변수는 초 단위의 값을 가지므로 5분 후에 실행하려면 300초를 지정하십시오.
기존 작업에 다음 논리를 추가한다고 가정해 보겠습니다.
@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"] )
그래서 응답의 상태 코드를 확인하는 로직을 추가했고, 200이 아닌 경우에는 해당 작업을 최대 2번까지 재시도합니다. 그러나 이러한 재시도는 두 시도 사이에 시간 차이 없이 발생합니다. 이제 이 작업에 대한 여러 시도를 지연하려면 어떻게 해야 할까요? retry_delay
인수를 전달하면 이를 수행할 수 있으며, 이는 초 단위로 값을 허용합니다.
@db_periodic_task(crontab(hour="18", minute="00"), retries=2, retry_delay=10)
이로 인해 여러 번 시도할 때마다 10초의 지연이 발생합니다.
Huey에는 Django에서 개발하는 동안 Huey 작업을 더 쉽게 해주는 기본 설정이 제공됩니다. 따라서 settings.py
파일에 DEBUG=True
있을 때마다 작업은 일반 함수 호출과 마찬가지로 동기적으로 실행됩니다. 이것의 목적은 테스트를 개발하거나 실행하는 동안 Redis와 추가 소비자 프로세스를 모두 실행하지 않도록 하는 것입니다. 이에 대한 자세한 내용은 여기에서 읽을 수 있습니다.
이를 위해 settings.py
에 다음 줄을 추가해야 합니다.
HUEY = {}
그러나 이 동작을 재정의하려면 대신 다음 Huey 구성을 추가하면 됩니다.
HUEY = { "immediate": False }
settings.py
에 위의 구성이 언급되어 있고 DEBUG=True
인 경우 Huey는 Redis를 설정하고 run_huey
명령을 사용하여 Huey Worker를 실행하도록 요구합니다.
Celery와 비교하여 Huey에 대한 몇 가지 관찰 사항은 다음과 같습니다.
run_huey
명령을 사용하여 하나의 서비스만 실행하면 됩니다.