metin oktay deniz

m e t i n

Yükleniyor

Django’da Celery ile Asenkron Görev Yönetimi
Yayınlanma Tarihi

21 Nisan 2025

Django’da Celery ile Asenkron Görev Yönetimi

Django projelerimde artan iş yüklerini arka planda asenkron olarak çalıştırmak için uzun zamandır Celery kullanıyorum. Bugün Celery’nin temellerini, Django ile nasıl entegre ettiğimi ve karşılaştığım küçük püf noktalarını kendi deneyimlerim üzerinden paylaşmak istiyorum.

Neden Celery?

Projeler büyüdükçe:

  • E‑posta gönderimleri,
  • Rapor üretimleri,
  • Dosya işleme,
  • Periyodik temizleme işleri

gibi işlemler ana application akışını yavaşlatabiliyor. Celery ile bu uzun süren işleri “task” olarak ayırıp, ayrı bir worker sürecinde çalıştırabiliyoruz. Böylece HTTP istekleri hız kesmeden yanıtlanıyor, kullanıcı deneyimi bozulmuyor.

Adım 1: Kurulum

Öncelikle celery ve bir broker (ben Redis kullanıyorum) paketlerini yüklüyorum:

pip install celery redis

Projede ayrıca Redis server’ın çalışıyor olması gerekiyor. (Docker’da hızlıca ayağa kaldırmak için: docker run -p 6379:6379 redis:latest)

Adım 2: Django ile Celery Yapılandırması

Projenin ana dizininde (örneğin myproject/) celery.py adında bir dosya oluşturuyorum:

# myproject/celery.py
import os
from celery import Celery

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')

app = Celery('myproject')
app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks()

Aynı dizindeki __init__.py içinde Celery uygulamasını yüklüyorum:

# myproject/__init__.py
from .celery import app as celery_app

__all__ = ('celery_app',)

Adım 3: Settings’te Gerekli Ayarlar

# settings.py

# Redis broker
CELERY_BROKER_URL = 'redis://127.0.0.1:6379/0'
# Task sonuçlarını saklamak isterseniz backend
CELERY_RESULT_BACKEND = 'redis://127.0.0.1:6379/1'

CELERY_TIMEZONE = 'Europe/Istanbul'
CELERY_ENABLE_UTC = False

Periyodik görevler için django-celery-beat kullanmak isterseniz:

pip install django-celery-beat

ve INSTALLED_APPS içine 'django_celery_beat' ekleyip migrate komutunu çalıştırmanız yeterli.

Adım 4: Task Yazmak

Herhangi bir app’in içinde tasks.py dosyası oluşturup görevleri tanımlıyorum. Örnek olarak e‑posta gönderimi:

# myapp/tasks.py
from celery import shared_task
from django.core.mail import send_mail

@shared_task
def send_welcome_email(user_id):
    from django.contrib.auth import get_user_model
    User = get_user_model()
    user = User.objects.get(pk=user_id)
    subject = 'Hoş Geldiniz!'
    message = f"Merhaba {user.first_name}, kayıt olduğunuz için teşekkürler."
    send_mail(subject, message, 'noreply@site.com', [user.email])
    return f"E‑posta gönderildi: {user.email}"

View ya da signal içinden çağırmak için:

# myapp/views.py

from .tasks import send_welcome_email

def register(request):
    new_user = form.save()
    send_welcome_email.delay(new_user.id)
    return redirect('success')

Adım 5: Worker ve Beat Çalıştırmak

# Worker başlat
celery -A myproject worker --loglevel=info

# Periyodik task’lar için (django-celery-beat)
celery -A myproject beat --loglevel=info

Production’da bu komutları systemd veya supervisor ile daemon olarak çalıştırıyorum.

Adım 6: Periyodik Görevler

Örnek eski kayıtları silen periyodik görev:

# myapp/tasks.py
@shared_task
def delete_old_records():
    from .models import LogEntry
    import datetime
    threshold = datetime.datetime.now() - datetime.timedelta(days=30)
    deleted, _ = LogEntry.objects.filter(timestamp__lt=threshold).delete()
    return f"{deleted} kayıt silindi."

Admin > Periodic Tasks > Add üzerinden cron ifadesiyle tanımlama yapabilirsiniz.

Adım 7: Monitoring (Flower)

pip install flower
celery -A myproject flower

Web arayüzünde görev akışı, kuyruk uzunluğu ve worker durumu gibi verileri izleyebiliyorum.

Küçük Püf Noktalar

  • Retry Mekanizması:

    @shared_task(bind=True, max_retries=3, default_retry_delay=60)
    def unreliable_task(self, ...):
        try:
            # riskli işlem
        except Exception as e:
            raise self.retry(exc=e)
    
  • Task Zaman Aşımı: CELERY_TASK_TIME_LIMIT = 300 ile uzun süren task’ları sınırlayın.
  • Kuyruk Ayrımı:

    send_welcome_email.apply_async((user.id,), queue='emails')
  • Transaction Güvenliği:

    from django.db import transaction
    transaction.on_commit(lambda: send_welcome_email.delay(user.id))
    

Celery ile Django’da asenkron çalışan, periyodik ve güvenilir bir iş kuyruğu altyapısı kurmak birkaç adımda tamamlanıyor. Umarım bu rehber, sizin projelerinizde arka plan işlemlerini yönetirken işinize yarar.

— Metin Oktay Deniz