Python Programming

برنامه‌ریزی وظایف در سطح تولید: هماهنگی وظایف Cron پایتون با Celery Beat و Redis

هنگام ساخت برنامه‌های مقیاس‌پذیر پایتون، تکیه بر وظایف سطح سیستم cron معمولاً با رشد زیرساخت شما به یک گلوگاه تبدیل می‌شود. اگرچه cron ساده است، اما از ویژگی‌های کلیدی برای میکروسرویس‌های مدرن مانند اجرای توزیع‌شده، مکانیزم‌های تکرار و نظارت متمرکز بی‌بهره است. اینجا Celery به همراه Celery Beat وارد می‌شود—یک راه‌حل قدرتمند برای زمان‌بندی وظایف دوره‌ای در محیطی توزیع‌شده. وقتی این پشته در کنار Redis به عنوان پیام‌رسان (message broker) استفاده می‌شود، قابلیت اطمینان و عملکرد مورد نیاز برای بارهای کاری در سطح تولید را ارائه می‌دهد.

چرا فراتر از Cron استاندارد برویم؟

وظایف Cron استاندارد به زمان و سیستم‌فایل میزبان گره خورده‌اند. اگر برای چندین کانتینر یا سرور استقرار انجام دهید، مدیریت همگام‌سازی و جلوگیری از شرایط رقابتی (race conditions) به یک کابوس تبدیل می‌شود. Celery Beat این مشکلات را با ارائه یک زمان‌بند متمرکز که اجرای وظایف را در گره‌های کارگر مدیریت می‌کند، حل می‌کند. این ابزار تنظیمات منطقه زمانی را انجام می‌دهد، اجرای حداقل یک‌بار (at-least-once) را تضمین می‌کند و به راحتی با ابزارهای نظارتی مانند Flower یکپارچه می‌شود.

معماری اصلی

برای راه‌اندازی این پشته، به سه جزء اصلی نیاز دارید:

  1. Celery Beat: زمان‌بندی که وظایف را در فواصل مشخص شده فعال می‌کند.
  2. Celery Workers: فرآیندهایی که منطق واقعی اجرای وظیفه را انجام می‌دهند.
  3. Redis: پیام‌رسانی که وظایف و نتایج را ذخیره می‌کند.

راه‌اندازی ساختار پروژه

بیایید یک چیدمان استاندارد پروژه را فرض کنیم. ما یک ماژول پایه tasks.py برای تعریف وظایف زمان‌بندی شده خود ایجاد خواهیم کرد. ابتدا مطمئن شوید که وابستگی‌های ضروری نصب شده‌اند:

pip install celery redis

سپس، بیایید یک برنامه Celery تعریف کرده و آن را برای استفاده از Redis پیکربندی کنیم. این پیکربندی معمولاً در یک فایل config.py انجام می‌شود:

# config.py
broker_url = 'redis://localhost:6379/0'
result_backend = 'redis://localhost:6379/0'
timezone = 'UTC'
enable_utc = True

اکنون می‌توانیم وظایف خود را در tasks.py تعریف کنیم. استفاده از دکوراتور @app.task به ما امکان می‌دهد خطاها و تلاش‌های مجدد را به صورت خودکار مدیریت کنیم.

# tasks.py
from celery import shared_task
from datetime import timedelta
from celery.schedules import crontab

@shared_task(bind=True, max_retries=3)
def send_weekly_report(self):
    try:
        # شبیه‌سازی ارسال ایمیل یا پردازش داده
        print("Sending weekly report...")
        return True
    except Exception as exc:
        raise self.retry(exc=exc)

پیکربندی Celery Beat برای زمان‌بندی

جادو در پیکربندی beat رخ می‌دهد. شما می‌توانید زمان‌بندی‌ها را مستقیماً در کد خود با استفاده از اشیاء crontab تعریف کنید یا آن‌ها را از یک فایل پیکربندی خارجی وارد کنید. در اینجا نحوه زمان‌بندی وظیفه send_weekly_report برای اجرا در ساعت ۹:۰۰ صبح هر دوشنبه آمده است:

# celery_config.py
from celery.schedules import crontab

beat_schedule = {
    'weekly-report': {
        'task': 'tasks.send_weekly_report',
        'schedule': crontab(hour=9, minute=0, day_of_week=1),
    },
}

این رویکرد اجازه می‌دهد تا منطق زمان‌بندی پیچیده بدون نوشتن حتی یک خط از سینتکس crontab سطح سیستم انجام شود. برای مثال، می‌توانید از timedelta برای فواصل ثابت نیز استفاده کنید:

from datetime import timedelta

beat_schedule = {
    'cleanup-cache': {
        'task': 'tasks.cleanup_cache',
        'schedule': timedelta(hours=2),
    },
}

اجرای سرویس‌ها

پس از پیکربندی، Redis را روی ماشین محلی یا سرور خود شروع کنید. سپس، کارگر Celery و زمان‌بند Beat را راه‌اندازی کنید. در یک محیط تولید، این‌ها باید به عنوان سرویس‌های سیستمی جداگانه (مثلاً با استفاده از systemd یا Docker Compose) اجرا شوند.

# Terminal 1: Start the worker
celery -A tasks worker --loglevel=info

# Terminal 2: Start the scheduler
celery -A tasks beat --loglevel=info

با جدا کردن فرآیندهای کارگر و beat، اطمینان حاصل می‌کنید که زمان‌بند سبک و پاسخگو باقی می‌ماند، در حالی که کارگران بر روی اجرا تمرکز می‌کنند.

بهترین شیوه‌ها برای محیط تولید

  • نظارت: همیشه Flower را در کنار پیکربندی Celery خود مستقر کنید. این ابزار یک داشبورد بلادرنگ برای نظارت بر نرخ موفقیت وظایف، تأخیر و سلامت کارگران ارائه می‌دهد.
  • مدیریت خطا: منطق تلاش مجدد قوی را با بازگشت نمایی (exponential backoff) پیاده‌سازی کنید تا خطاهای گذرا را به آرامی مدیریت کنید.
  • منطقه زمانی: همیشه تنظیمات timezone و enable_utc را به صراحت تنظیم کنید تا از سردرگمی زمانی که وظایف در مناطق جغرافیایی مختلف اجرا می‌شوند، جلوگیری شود.
  • جداپذیری (Idempotency): اطمینان حاصل کنید که وظایف شما جداپذیر هستند. حتی با تضمین‌های تحویل "حداقل یک‌بار"، مشکلات شبکه ممکن است باعث تحویل تکراری وظایف شود.

نتیجه‌گیری

مهاجرت از cron سیستمی به Celery Beat و Redis یک گام مهم به سمت ساخت بک‌اند‌های پایتون مقاوم و مقیاس‌پذیر است. اگرچه راه‌اندازی اولیه به پیکربندی بیشتری نسبت به یک خط crontab ساده نیاز دارد، اما مزایای آن از نظر قابلیت اطمینان، نظارت و اجرای توزیع‌شده بی‌نظیر است. با دنبال کردن بهترین شیوه‌ها و بهره‌گیری از قدرت Redis به عنوان پیام‌رسان، می‌توانید اطمینان حاصل کنید که وظایف پس‌زمینه شما حتی تحت بار کاری سنگین به روانی اجرا می‌شوند.

Share: