حول المحتوى:
شرح كيفية تنفيذ المهام الخلفية باستخدام Celery وRQ وFastAPI BackgroundTasks، ومقارنة بين هذه الحلول.
في كثير من تطبيقات الويب نحتاج لتنفيذ مهام تأخذ وقتًا طويلاً دون أن نُبطئ استجابة الـ API أو واجهة المستخدم، مثل إرسال رسائل بريدية، معالجة صور، توليد تقارير، أو استدعاء خدمات خارجية. هنا يأتي دور Background tasks مع أطر مثل Django وFastAPI.
في هذا المقال على افهم صح سنشرح كيفية التعامل مع Background tasks Django FastAPI باستخدام:
كما سنقارن بين هذه الحلول، ومتى تختار كل واحد منها، مع ربط الموضوع بمفاهيم مثل البرمجة غير المتزامنة والـ APIs. إذا لم تكن معتادًا على FastAPI يمكنك الرجوع إلى مقالنا بناء RESTful APIs باستخدام FastAPI، ولتعمّق أكبر في مفهوم اللا تزامن في بايثون راجع البرمجة غير المتزامنة في بايثون.
في التطبيقات التقليدية (Synchronous)، كل Request يُنفّذ في Thread أو Process واحد، وأي عملية ثقيلة (مثل إرسال 1000 إيميل) ستُبطئ الاستجابة أو تؤدي لانتهاء المهلة (Timeout).
بدلاً من تنفيذ هذه العمليات داخل نفس طلب الـ HTTP، نقوم بـ:
هذا النمط أساسي لتطبيقات عالية الأداء، خاصة مع Django وFastAPI، ويكمّل ما تتعلّمه في موضوعات مثل Threading في بايثون والبرمجة غير المتزامنة.
الحلول الأكثر شهرة لبيثون في هذا المجال:
Django بنفسه لا يوفّر نظام Background Tasks متكامل، لكنه يتكامل بسهولة مع Celery. إذا كنت تبني نظامًا كبيرًا (E-commerce، SaaS) يحتاج لمهام معقدة (سلاسل Tasks، جدولة، Retries)، فـ Celery غالبًا هو الخيار الأول.
نفترض أن لديك مشروع Django جاهز. إن لم يكن لديك خبرة كافية مع Django راجع الدليل الشامل حول إطار Django.
pip install celery[redis] redis هنا نستعمل Redis كـ Broker (يمكنك استخدام RabbitMQ أو غيره).
في نفس مجلد settings.py (غالبًا مجلد المشروع الرئيسي):
# project_name/celery.py
import os
from celery import Celery
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project_name.settings")
app = Celery("project_name")
# قراءة الإعدادات من Django واستخدام namespace للـ CELERY_*
app.config_from_object("django.conf:settings", namespace="CELERY")
# اكتشاف المهام تلقائيًا من apps المسجلة
app.autodiscover_tasks() وفي ملف __init__.py لنفس مجلد المشروع:
# project_name/__init__.py
from .celery import app as celery_app
__all__ = ("celery_app",) # settings.py
CELERY_BROKER_URL = "redis://localhost:6379/0"
CELERY_RESULT_BACKEND = "redis://localhost:6379/1" في أي app داخل المشروع، أنشئ ملف tasks.py:
# app_name/tasks.py
from celery import shared_task
from django.core.mail import send_mail
@shared_task
def send_welcome_email(user_email):
send_mail(
subject="مرحبًا بك",
message="شكرًا لتسجيلك في موقعنا.",
from_email="[email protected]",
recipient_list=[user_email],
fail_silently=False,
) يمكنك استدعاء المهمة في الخلفية بدلًا من تنفيذها مباشرة:
# app_name/views.py
from django.http import JsonResponse
from .tasks import send_welcome_email
def register_user(request):
# من المفترض هنا إنشاء المستخدم وحفظه في قاعدة البيانات
user_email = "[email protected]"
# استدعاء المهمة في الخلفية
send_welcome_email.delay(user_email)
return JsonResponse({"detail": "تم التسجيل وسيصلك بريد ترحيبي قريبًا"}) celery -A project_name worker -l info يمكنك أيضًا تشغيل Beat للمهام المجدولة، لكن هذا خارج نطاق هذه المقدمة.
إذا كنت تحتاج لحل أبسط من Celery، وتستخدم Redis بالفعل، فـ RQ خيار ممتاز. يناسب المشاريع الصغيرة والمتوسطة، أو الحالات التي لا تحتاج كل خصائص Celery.
pip install rq redis django-rq INSTALLED_APPS = [
# ...
"django_rq",
]
RQ_QUEUES = {
"default": {
"HOST": "localhost",
"PORT": 6379,
"DB": 0,
"DEFAULT_TIMEOUT": 360,
}
} # urls.py
from django.urls import path, include
urlpatterns = [
# ...
path("django-rq/", include("django_rq.urls")),
] # app_name/tasks.py
import time
def long_running_task(user_id):
# مثال لمهمة تستغرق وقتًا
time.sleep(10)
print(f"تم تنفيذ المهمة للمستخدم {user_id}") استدعاء المهمة من View:
# app_name/views.py
import django_rq
from django.http import JsonResponse
from .tasks import long_running_task
def trigger_task(request):
queue = django_rq.get_queue("default")
job = queue.enqueue(long_running_task, user_id=123)
return JsonResponse({"job_id": job.id, "status": "queued"}) python -m rq worker default FastAPI يوفر كلاس جاهز اسمه BackgroundTasks لتنفيذ مهام خفيفة في الخلفية بعد إرجاع الاستجابة. هذا الحل لا يعتمد على Redis أو RabbitMQ؛ المهام تُنفذ داخل نفس عملية السيرفر.
هذا مناسب لـ:
from fastapi import FastAPI, BackgroundTasks
app = FastAPI()
def send_email(email: str, message: str):
# من المفترض هنا تنفيذ منطق الإرسال الفعلي
print(f"إرسال بريد إلى {email}: {message}")
@app.post("/register")
def register_user(email: str, background_tasks: BackgroundTasks):
# منطق التسجيل...
# إضافة مهمة للإرسال في الخلفية
background_tasks.add_task(send_email, email, "مرحبًا بك في موقعنا!")
return {"detail": "تم التسجيل، وسيتم إرسال رسالة ترحيبية في الخلفية"} بمجرد إرجاع الاستجابة، يقوم FastAPI بتشغيل الوظائف المُضافة إلى background_tasks في Thread منفصل (أو Event Loop) لكن داخل نفس عملية التطبيق. لا يوجد Broker خارجي أو Worker مستقل.
في هذه الحالات ستحتاج لحلول مثل Celery أو RQ مع FastAPI أيضًا، وعندها يكون تعلم الدوكر مفيدًا جدًا لتشغيل Workers وBrokers داخل حاويات منفصلة.
مثلما فعلنا مع Django، يمكن أيضًا استخدام Celery أو RQ مع FastAPI. الفكرة العامة:
celery_app.py).task.delay(...) (Celery) أو queue.enqueue(...) (RQ).# celery_app.py
from celery import Celery
celery_app = Celery(
"fastapi_app",
broker="redis://localhost:6379/0",
backend="redis://localhost:6379/1",
)
@celery_app.task
def process_video(video_id: int):
# منطق معالجة فيديو ثقيل
return {"status": "done", "video_id": video_id} في ملف FastAPI الرئيسي:
# main.py
from fastapi import FastAPI
from celery_app import process_video
app = FastAPI()
@app.post("/videos/{video_id}/process")
def process_video_endpoint(video_id: int):
job = process_video.delay(video_id)
return {"task_id": job.id, "status": "queued"} بهذا الشكل تحصل على أفضل ما في FastAPI (سرعة الـ API) مع قوة Celery في الـ Background Tasks.
django-rq أو rq-dashboard.async/await عن Task Queue كامل إذا كانت العمليات I/O Bound وليست CPU Bound.فهم Background tasks Django FastAPI خطوة أساسية لتصميم تطبيقات ويب قوية وقابلة للتوسع. مع اختيار الأداة المناسبة (Celery، RQ، أو FastAPI BackgroundTasks) ستتمكن من عزل المهام الثقيلة عن استجابة المستخدم، وتحسين الأداء بشكل ملحوظ.
لإكمال الصورة حول بناء APIs عالية الأداء، يمكنك الاطلاع أيضًا على:
شرح كيفية تنفيذ المهام الخلفية باستخدام Celery وRQ وFastAPI BackgroundTasks، ومقارنة بين هذه الحلول.
مساحة اعلانية