Sellerie mit Django für die Hintergrundverarbeitung verwenden

Webanwendungen beginnen in der Regel einfach, können jedoch recht komplex werden, und die meisten von ihnen überschreiten schnell die Verantwortung, nur auf HTTP-Anforderungen zu antworten.

In diesem Fall muss unterschieden werden, was sofort geschehen muss (normalerweise im HTTP-Anforderungslebenszyklus) und was eventuell passieren kann. Warum das? Nun, denn wenn Ihre Anwendung mit Verkehr überlastet wird, machen einfache Dinge wie diese den Unterschied. 

Vorgänge in einer Webanwendung können als kritische Vorgänge oder Anforderungszeitvorgänge und Hintergrundaufgaben klassifiziert werden, die außerhalb der Anforderungszeit stattfinden. Diese sind den oben beschriebenen zugeordnet: 

  • muss sofort geschehen: Anforderungszeitoperationen
  • muss irgendwann passieren: Hintergrundaufgaben

Anforderungszeitvorgänge können für einen einzelnen Anforderungs- / Antwortzyklus ausgeführt werden, ohne zu befürchten, dass der Vorgang abläuft oder dass der Benutzer schlechte Erfahrungen macht. Häufige Beispiele sind CRUD-Vorgänge (Erstellen, Lesen, Aktualisieren, Löschen) und Benutzerverwaltung (Login / Logout-Routinen)..

Hintergrundaufgaben sind unterschiedlich, da sie in der Regel recht zeitaufwändig sind und zumeist aufgrund externer Abhängigkeiten ausfallen. Einige häufige Szenarien in komplexen Webanwendungen sind:

  • Versenden von Bestätigungs- oder Aktivitäts-E-Mails
  • tägliches Krabbeln und Verschrotten einiger Informationen aus verschiedenen Quellen und Speichern dieser
  • Datenanalyse durchführen
  • Löschen nicht benötigter Ressourcen
  • Exportieren von Dokumenten / Fotos in verschiedenen Formaten

Hintergrundaufgaben stehen im Mittelpunkt dieses Tutorials. Das am häufigsten verwendete Programmiermuster für dieses Szenario ist die Producer Consumer Architecture. 

In einfachen Worten kann diese Architektur folgendermaßen beschrieben werden: 

  • Produzenten erstellen Daten oder Aufgaben.
  • Aufgaben werden in eine Warteschlange gestellt, die als Aufgabenwarteschlange bezeichnet wird. 
  • Die Verbraucher sind dafür verantwortlich, die Daten zu verbrauchen oder die Aufgaben auszuführen. 

Normalerweise rufen die Konsumenten Aufgaben aus der Warteschlange auf eine FIFO-Methode (First-In-First-Out) oder entsprechend ihrer Prioritäten ab. Die Konsumenten werden auch als Arbeiter bezeichnet, und dies ist der Begriff, den wir durchgehend verwenden werden, da er mit der Terminologie der erörterten Technologien übereinstimmt.

Welche Aufgaben können im Hintergrund bearbeitet werden? Aufgaben, die:

  • sind für die grundlegende Funktionalität der Webanwendung nicht wesentlich
  • kann nicht im Anforderungs- / Antwortzyklus ausgeführt werden, da sie langsam sind (I / O-intensiv usw.)
  • von externen Ressourcen abhängen, die möglicherweise nicht verfügbar sind oder sich nicht wie erwartet verhalten
  • Möglicherweise muss mindestens einmal wiederholt werden
  • müssen nach einem Zeitplan ausgeführt werden

Sellerie ist die erste Wahl für die Hintergrundverarbeitung im Python / Django-Ökosystem. Es hat eine einfache und übersichtliche API und lässt sich hervorragend in Django integrieren. Es unterstützt verschiedene Technologien für die Aufgabenwarteschlange und verschiedene Paradigmen für die Arbeiter.

In diesem Lernprogramm erstellen wir eine Django-Spielzeug-Webanwendung (die sich mit realen Szenarien befasst), die Hintergrundaufgabenverarbeitung verwendet.

Dinge einrichten

Vorausgesetzt, Sie sind bereits mit Python-Paketverwaltung und virtuellen Umgebungen vertraut, installieren wir Django:

$ pip installieren Django

Ich habe mich entschlossen, eine weitere Blogging-Anwendung zu erstellen. Der Fokus der Anwendung liegt auf der Einfachheit. Ein Benutzer kann einfach ein Konto erstellen und ohne großen Aufwand einen Beitrag erstellen und auf der Plattform veröffentlichen. 

Richten Sie das ein quick_publisher Django-Projekt:

$ django-admin startproject quick_publisher

Lass uns die App starten lassen:

$ cd quick_publisher $ ./manage.py startapp main

Wenn ich ein neues Django-Projekt beginne, erstelle ich gerne ein Main Anwendung, die unter anderem ein benutzerdefiniertes Benutzermodell enthält. Meistens stoße ich auf Einschränkungen des Standard-Django Nutzer Modell. Einen Brauch haben Nutzer Das Modell gibt uns den Vorteil der Flexibilität.

# main / models.py aus django.db importiert Modelle aus django.contrib.auth.models importiert AbstractBaseUser, PermissionsMixin, BaseUserManager-Klasse UserAccountManager (BaseUserManager): use_in_migrations = True def_create_user (if, default, _ extra_fields): if Keine E-Mail: Erhöhung von ValueError ('E-Mail-Adresse muss angegeben werden') Wenn kein Kennwort: Erhöhung von ValueError ('Kennwort muss angegeben werden') E-Mail = self.normalize_email (E-Mail) user = Self.model (E-Mail = E-Mail, ** extra_fields) user.set_password (password) user.save (using = self._db) return user def create_user (self, email = keine, password = keine, ** extra_fields): return self._create_user (email, password, ** extra_fields) def create_superuser (self, email, password, ** extra_fields): extra_fields ['is_staff'] = True extra_fields ['is_superuser'] = True return self._create_user (email, password, ** extra_fields) Klasse Benutzer (AbstractBaseUser, PermissionsMixin): REQUIRED_FIELDS = [] USERNAME_FIELD = 'email' objects = UserAccountManager () email = models.EmailField ('email', unique = True, blank = False, null = False) full_name = models.CharField ('full name', blank = True, null = True, max_length = 400) is_staff = models.BooleanField ('staff status' , default = False) is_active = models.BooleanField ('active', default = True) def get_short_name (self): return self.email def get_full_name (self): return self.email def __unicode __ (self): return self.email

Sehen Sie sich die Django-Dokumentation an, wenn Sie nicht wissen, wie benutzerdefinierte Benutzermodelle funktionieren.

Jetzt müssen wir Django anweisen, dieses Benutzermodell anstelle des Standardmodells zu verwenden. Fügen Sie diese Zeile dem hinzu quick_publisher / settings.py Datei:

AUTH_USER_MODEL = 'main.User' 

Wir müssen auch das hinzufügen Main Anwendung auf die INSTALLED_APPS Liste in der quick_publisher / settings.py Datei. Wir können jetzt die Migrationen erstellen, sie anwenden und einen Superuser erstellen, um sich im Django-Verwaltungsbereich anmelden zu können:

$ ./manage.py makemigrations main $ ./manage.py migrate $ ./manage.py erstellt einen Superuser

Lassen Sie uns nun eine eigene Django-Anwendung erstellen, die für Beiträge zuständig ist:

$ ./manage.py startapp publish

Definieren wir ein einfaches Post-Modell in Verlag / models.py:

Importieren von Modellen aus django.utils aus django.db importieren der Zeitzone aus django.contrib.auth import Klasse "get_user_model" Post (models.Model): author = models.ForeignKey (get_user_model ()) erstellt = models.DateTimeField (Standardwert "Created Date") = timezone.now) title = models.CharField ('Title', max_length = 200) content = models.TextField ('Content') slug = models.SlugField ('Slug') def __str __ (self): return '"% s "von% s '% (self.title, self.author)

Anhaken der Post Modell mit dem Django-Admin wird in der gemacht Herausgeber / admin.py Datei wie folgt:

aus django.contrib import admin aus .models import Post @ admin.register (Post) Klasse PostAdmin (admin.ModelAdmin): pass

Zum Schluss haken wir die Herausgeber Anwendung mit unserem Projekt durch Hinzufügen zum INSTALLED_APPS Liste.

Wir können jetzt den Server laufen lassen und zu gehen http: // localhost: 8000 / admin / und erstelle unsere ersten Beiträge, damit wir etwas zu spielen haben:

$ ./manage.py runserver

Ich vertraue darauf, dass Sie Ihre Hausaufgaben gemacht und die Beiträge erstellt haben. 

Lass uns weitermachen. Der nächste naheliegende Schritt ist das Erstellen einer Möglichkeit, die veröffentlichten Beiträge anzuzeigen. 

# publisher / views.py aus django.http import Http404 aus django.shortcuts import rendern von .models import Post def view_post (request, slug): try: post = Post.objects.get (slug = slug) außer Post.DoesNotExist: Http404 ("Umfrage existiert nicht") return Rendern (request, 'post.html', context = 'post': post)

Verbinden Sie unsere neue Ansicht mit einer URL in: quick_publisher / urls.py

# quick_publisher / urls.py aus django.conf.urls import url aus django.contrib import admin aus publisher.views import view_post urlpatterns = [url (r '^ admin /'), admin.site.urls), url (r '^ (? P[a-zA-Z0-9 \ -] +) ', view_post, name = "view_post")]

Schließlich erstellen wir die Vorlage, in der der Beitrag dargestellt wird: Herausgeber / templates / post.html

       

post.title

post.content

Veröffentlicht von post.author.full_name am post.created

Wir können jetzt im Browser zu http: // localhost: 8000 / the-slug-of-the-post-you-created / gelangen. Es ist nicht gerade ein Wunder des Webdesigns, aber gut aussehende Beiträge zu erstellen, würde den Rahmen dieses Tutorials sprengen.

Senden von Bestätigungsemails

Hier ist das klassische Szenario:

  • Sie erstellen ein Konto auf einer Plattform.
  • Sie geben eine E-Mail-Adresse an, um auf der Plattform eindeutig identifiziert zu werden.
  • Die Plattform prüft, ob Sie tatsächlich der Inhaber der E-Mail-Adresse sind, indem Sie eine E-Mail mit einem Bestätigungslink senden.
  • Bis Sie die Überprüfung durchführen, können Sie die Plattform nicht (vollständig) verwenden.

Fügen wir ein is_verified Flagge und die Verifizierungs_Uuid auf der Nutzer Modell:

# main / models.py import uuid-Klasse Benutzer (AbstractBaseUser, PermissionsMixin): REQUIRED_FIELDS = [] USERNAME_FIELD = 'email' objects = UserAccountManager () email = models.EmailField ('email', eindeutig = True, leer = null) False) full_name = models.CharField ('vollständiger Name', leer = True, null = True, max_length = 400) is_staff = models.BooleanField ('staff status', default = False) is_active = models.BooleanField ('active', default = True) is_verified = models.BooleanField ('verifiziert', default = False) # Fügen Sie das Flag 'is_verified' verification_uuid = models.UUIDField ('Eindeutige Überprüfungs-UUID', default = uuid.uuid4) def get_short_name (self): return hinzu self.email def get_full_name (self): return self.email def __unicode __ (self): self.email zurückgeben

Nutzen Sie diese Gelegenheit, um das Benutzermodell dem Administrator hinzuzufügen:

aus django.contrib import admin aus .models import User @ admin.register (User) Klasse UserAdmin (admin.ModelAdmin): übergeben

Lassen Sie uns die Änderungen in der Datenbank widerspiegeln:

$ ./manage.py makemigrations $ ./manage.py migrieren

Wir müssen jetzt einen Code schreiben, der eine E-Mail sendet, wenn eine Benutzerinstanz erstellt wird. Dafür gibt es Django-Signale, und dies ist eine perfekte Gelegenheit, um dieses Thema zu berühren. 

Signale werden ausgelöst, bevor / nachdem bestimmte Ereignisse in der Anwendung auftreten. Wir können Callback-Funktionen definieren, die automatisch ausgelöst werden, wenn die Signale ausgelöst werden. Um einen Rückruf auszulösen, müssen wir ihn zunächst mit einem Signal verbinden.

Wir erstellen einen Rückruf, der ausgelöst wird, nachdem ein Benutzermodell erstellt wurde. Wir werden diesen Code nach dem hinzufügen Nutzer Modelldefinition in: main / models.py

von django.db.models importiere Signale von django.core.mail import send_mail def user_post_save (Sender, Instanz, Signal, * args, ** kwargs): Wenn nicht instance.is_verified: # Bestätigungs-E-Mail senden send_mail ('Bestätigen Sie Ihr QuickPublisher-Konto ',' Folgen Sie diesem Link, um Ihr Konto zu überprüfen: "http: // localhost: 8000% s '% reverse (' verify ', kwargs = ' uuid ': str (instance.verification_uuid))' von @ quickpublisher. dev ', [instance.email], fail_silently = False,) signals.post_save.connect (user_post_save, sender = User)

Was wir hier gemacht haben, ist ein user_post_save Funktion und verbunden mit dem post_save Signal (eins, das ausgelöst wird, nachdem ein Modell gespeichert wurde), das vom gesendet wird Nutzer Modell-.

Django versendet E-Mails nicht nur alleine. Es muss an einen E-Mail-Dienst gebunden sein. Der Einfachheit halber können Sie Ihre Google Mail-Anmeldeinformationen hinzufügen quick_publisher / settings.py, oder Sie können Ihren bevorzugten E-Mail-Anbieter hinzufügen. 

So sieht die Google Mail-Konfiguration aus:

EMAIL_USE_TLS = True EMAIL_HOST = 'smtp.gmail.com' EMAIL_HOST_USER = '@ gmail.com 'EMAIL_HOST_PASSWORD =''EMAIL_PORT = 587

Um dies zu testen, gehen Sie in den Adminbereich und erstellen Sie einen neuen Benutzer mit einer gültigen E-Mail-Adresse, die Sie schnell überprüfen können. Wenn alles gut gegangen ist, erhalten Sie eine E-Mail mit einem Bestätigungslink. Die Verifizierungsroutine ist noch nicht fertig. 

So überprüfen Sie das Konto:

# main / views.py aus django.http import Http404 aus django.shortcuts import rendern, von .models umleiten importieren Benutzer def home (request): return render (request, 'home.html') def verify (request, uuid): try: user = User.objects.get (Verification_uuid = uuid, is_verified = False), außer User.DoesNotExist: raise Http404 ("Benutzer ist nicht vorhanden oder ist bereits verifiziert") user.is_verified = True user.save () return redirect ( 'Zuhause')

Verbinden Sie die Ansichten in: quick_publisher / urls.py

# quick_publisher / urls.py aus django.conf.urls import url aus django.contrib import admin aus publisher.views import view_post aus main.views import home, verifiziere urlpatterns = [url (r '^ $', home, name = " home "), url (r '^ admin /', admin.site.urls), url (r '^ verify / (? P[a-z0-9 \ -] +) / ', verify, name = "verify"), URL (r' ^ (? P[a-zA-Z0-9 \ -] +) ', view_post, name = "view_post")]

Denken Sie auch daran, eine home.html Datei unter main / templates / home.html. Es wird von der gerendert Zuhause Aussicht.

Versuchen Sie, das gesamte Szenario noch einmal auszuführen. Wenn alles in Ordnung ist, erhalten Sie eine E-Mail mit einer gültigen Bestätigungs-URL. Wenn Sie der URL folgen und dann den Administrator einchecken, können Sie sehen, wie das Konto überprüft wurde.

E-Mails asynchron versenden

Hier ist das Problem mit dem, was wir bisher gemacht haben. Sie haben vielleicht bemerkt, dass das Erstellen eines Benutzers etwas langsam ist. Das liegt daran, dass Django die Bestätigungs-E-Mail innerhalb der Anforderungszeit sendet. 

So funktioniert es: Wir senden die Benutzerdaten an die Django-Anwendung. Die Anwendung erstellt eine Nutzer erstellen und dann eine Verbindung zu Google Mail (oder einem anderen ausgewählten Dienst) herstellen. Django wartet auf die Antwort und sendet nur dann eine Antwort an unseren Browser. 

Hier kommt Celery ins Spiel. Stellen Sie zunächst sicher, dass es installiert ist:

$ pip installiere Sellerie

Wir müssen jetzt eine Sellerie-Anwendung in unserer Django-Anwendung erstellen:

# quick_publisher / celler.py importieren aus Sellerie importieren Celery os.environ.setdefault ('DJANGO_SETTINGS_MODULE', 'quick_publisher.settings') app = Celery ('quick_publisher') app.config_from_object ('django.conf: settings') # Laden Taskmodule aus allen registrierten Django-App-Konfigurationen. app.autodiscover_tasks ()

Sellerie ist eine Warteschlange. Es erhält Aufgaben von unserer Django-Anwendung und führt sie im Hintergrund aus. Sellerie muss mit anderen Diensten gekoppelt werden, die als Makler fungieren. 

Makler, die das Versenden von Nachrichten zwischen der Webanwendung und Celery übermitteln. In diesem Tutorial verwenden wir Redis. Redis ist einfach zu installieren und wir können ohne großen Aufwand damit beginnen.

Sie können Redis installieren, indem Sie die Anweisungen auf der Schnellstartseite von Redis befolgen. Sie müssen die Redis Python-Bibliothek installieren, pip install redis, und das erforderliche Paket für die Verwendung von Redis und Sellerie: Pip Install Sellerie [Redis].

Starten Sie den Redis-Server in einer separaten Konsole wie folgt: $ redis-server

Fügen wir die mit Celery / Redis verbundenen Konfigurationen hinzu quick_publisher / settings.py:

# REDIS-bezogene Einstellungen REDIS_HOST = 'localhost' REDIS_PORT = '6379' BROKER_URL = 'redis: //' + REDIS_HOST + ':' + REDIS_PORT + '/ 0' BROKER_TRANSPORT_OPTIONS = 'Sichtbarkeitszeit': 3600 CELERY_RESULT_BACKEND = ' / '+ REDIS_HOST +': '+ REDIS_PORT +' / 0 '

Bevor in Celery etwas ausgeführt werden kann, muss es als Task deklariert werden. 

So gehen Sie vor:

# main / task.py import logging aus django.urls importiere reverse aus django.core.mail import send_mail aus django.contrib.auth import get_user_model aus quick_publisher.celery import app @ app.task def send_verification_email (user_id): UserModel = get_user_model ( ) try: user = UserModel.objects.get (pk = user_id) send_mail ('QuickPublisher-Konto überprüfen', 'Klicken Sie auf diesen Link, um Ihr Konto zu überprüfen: "http: // localhost: 8000% s'% reverse ('verify' , kwargs = 'uuid': str (user.verification_uuid)), '[email protected]', [user.email], fail_silently = False,) mit Ausnahme von UserModel.DoesNotExist: logging.warning ("Es wurde versucht, die Bestätigung zu senden E-Mail an nicht vorhandenen Benutzer '% s' "% user_id)

Was wir hier gemacht haben, ist folgendes: Wir haben die E-Mail-Funktion zum Senden von Bestätigungen in eine andere Datei verschoben Aufgaben.py

Ein paar Anmerkungen:

  • Der Name der Datei ist wichtig. Sellerie geht alle Apps durch INSTALLED_APPS und registriert die Aufgaben in Aufgaben.py Dateien.
  • Beachten Sie, wie wir das dekoriert haben Senden Sie E-Mail-Verifizierung Funktion mit @ app.task. Dies teilt Celery mit, dass dies eine Aufgabe ist, die in der Aufgabenwarteschlange ausgeführt wird.
  • Beachten Sie, wie wir als Argument erwarten Benutzeridentifikation eher als ein Nutzer Objekt. Dies liegt daran, dass wir beim Senden der Aufgaben an Celery möglicherweise Probleme beim Serialisieren komplexer Objekte haben. Es ist am besten, sie einfach zu halten.

Zurück gehen zu main / models.py, Der Signalcode wird zu:

von django.db.models importiere Signale aus main.tasks import send_verification_email importieren def user_post_save (Sender, Instanz, Signal, * args, ** kwargs): Wenn nicht instance.is_verified: # Sende die Bestätigungs-E-Mail send_verification_email.delay (instance.pk) .post_save.connect (user_post_save, sender = Benutzer)

Beachten Sie, wie wir das nennen .verzögern Methode für das Aufgabenobjekt. Das heißt, wir schicken die Aufgabe an Celery und warten nicht auf das Ergebnis. Wenn wir verwendet haben send_verification_email (instance.pk) Stattdessen würden wir sie immer noch an Celery senden, aber warten, bis die Aufgabe abgeschlossen ist, was wir nicht wollen.

Bevor Sie mit dem Erstellen eines neuen Benutzers beginnen, gibt es einen Haken. Sellerie ist ein Service, und wir müssen damit anfangen. Öffnen Sie eine neue Konsole, stellen Sie sicher, dass Sie die entsprechende Virtualenv aktiviert haben, und navigieren Sie zum Projektordner.

$ Sellerie-Worker -A quick_publisher --loglevel = debug --concurrency = 4

Damit werden vier Sellerie-Prozessmitarbeiter gestartet. Ja, jetzt können Sie endlich einen anderen Benutzer erstellen. Beachten Sie, dass es keine Verzögerung gibt, und achten Sie darauf, die Protokolle in der Celery-Konsole zu überwachen und zu prüfen, ob die Aufgaben ordnungsgemäß ausgeführt werden. Das sollte ungefähr so ​​aussehen:

[2017-04-28 15: 00: 09,190: DEBUG / MainProcess] Aufgabe angenommen: main.tasks.send_verification_email [f1f41e1f-ca39-43d2-a37d-9de085dc99de] pid: 62065 [2017-04-28 15: 00: 11,740: INFO / PoolWorker-2] Die Task main.tasks.send_verification_email [f1f41e1f-ca39-43d2-a37d-9de085dc99de] gelang in 2.5500912349671125s: Keine

Periodische Aufgaben mit Sellerie

Hier ist ein anderes allgemeines Szenario. Die meisten ausgereiften Webanwendungen senden ihren Benutzern Lebenszyklus-E-Mails, um sie weiterhin zu beschäftigen. Einige häufige Beispiele für Lebenszyklus-E-Mails:

  • Monatliche Reportagen
  • Aktivitätsbenachrichtigungen (Likes, Freundschaftsanfragen usw.)
  • Erinnerungen an bestimmte Aktionen ("Vergiss nicht, deinen Account zu aktivieren")

Folgendes tun wir in unserer App. Wir werden zählen, wie oft jeder Beitrag angesehen wurde, und einen täglichen Bericht an den Autor senden. Einmal jeden Tag werden wir alle Benutzer durchgehen, ihre Beiträge abrufen und eine E-Mail mit einer Tabelle senden, die die Beiträge und die Anzahl der Aufrufe enthält.

Ändern wir das Post Modell, so dass wir das View-Count-Szenario aufnehmen können.

Klasse Post (models.Model): author = models.ForeignKey (User) erstellt = models.DateTimeField ('Erstellungsdatum', Standard = timezone.now) title = models.CharField ('Title', max_length = 200) content = models .TextField ('Content') slug = models.SlugField ('Slug') view_count = models.IntegerField ("View Count", default = 0) def __str __ (self): Rückgabe von% s '% ( self.title, self.author)

Wie immer müssen Sie beim Ändern eines Modells die Datenbank migrieren:

$ ./manage.py makemigrations $ ./manage.py migrieren

Lassen Sie uns auch das ändern view_post Django-Ansicht, um Ansichten zu zählen:

def view_post (request, slug): try: post = Post.objects.get (slug = slug) außer Post.DoesNotExist: raise Http404 ("Umfrage existiert nicht") post.view_count + = 1 post.save () return render (request, 'post.html', context = 'post': post)

Es wäre nützlich, das anzuzeigen view_count in der Vorlage. Füge das hinzu 

Gesehen post.view_count mal

 irgendwo in der Herausgeber / templates / post.html Datei. Machen Sie jetzt ein paar Ansichten zu einem Beitrag und sehen Sie, wie der Zähler steigt.

Lassen Sie uns eine Sellerie-Aufgabe erstellen. Da es sich um Posts handelt, werde ich sie in einfügen Verlag / Aufgaben.py:

aus django.template importieren Vorlage, Kontext aus django.core.mail import send_mail aus django.contrib.auth import get_user_model aus quick_publisher.celery importieren aus publisher.models importieren Post REPORT_TEMPLATE = "" "So haben Sie es bisher gemacht: % für Beitrag in Beiträgen% "post.title": post.view_count mal angesehen | % endfor% "" "" @ "app.task def send_view_count_report (): für Benutzer in get_user_model (). objects.all (): posts = Post.objects.filter (Autor = Benutzer) Wenn keine Beiträge vorhanden sind: continue template = Vorlage (REPORT_TEMPLATE) send_mail ('Ihre QuickPublisher-Aktivität', template.render (Kontext = Kontext ('posts': posts)), '[email protected]', [user.email], fail_silently = False,)

Vergessen Sie nicht, den Celery-Prozess neu zu starten, wenn Sie Änderungen an den Celery-Aufgaben vornehmen. Sellerie muss Aufgaben erkennen und neu laden. Bevor Sie eine periodische Aufgabe erstellen, sollten Sie dies in der Django-Shell testen, um sicherzustellen, dass alles wie vorgesehen funktioniert:

$ ./manage.py-Shell In [1]: von publisher.tasks import send send_view_count_report In [2]: send_view_count_report.delay ()

Hoffentlich haben Sie in Ihrer E-Mail einen kleinen Bericht erhalten. 

Lassen Sie uns nun eine periodische Aufgabe erstellen. Aufmachen quick_publisher / cellery.py und registrieren Sie die periodischen Aufgaben:

# quick_publisher / celler.py importieren aus Sellerie importieren Sellerie aus Sellerie.schedeln import crontab os.environ.setdefault ('DJANGO_SETTINGS_MODULE', 'quick_publisher.settings') : settings ') # Taskmodule aus allen registrierten Django-App-Konfigurationen laden. app.autodiscover_tasks () app.conf.beat_schedule = 'send-report-every-single-minute': 'task': 'publisher.tasks.send_view_count_report', 'schedule': crontab (), # change in 'crontab (Minute = 0, Stunde = 0) 'wenn Sie möchten, dass es täglich um Mitternacht ausgeführt wird,

Bisher haben wir einen Zeitplan erstellt, der die Aufgabe ausführen würde publisher.tasks.send_view_count_report jede Minute wie von der crontab () Notation. Sie können auch verschiedene Zeitpläne für Sellerie-Crontab angeben. 

Öffnen Sie eine andere Konsole, aktivieren Sie die entsprechende Umgebung und starten Sie den Celery Beat-Dienst. 

$ Sellerie - Ein schneller Verleger

Die Aufgabe des Beat-Service ist es, Aufgaben in Celery gemäß dem Zeitplan zu pushen. Beachten Sie, dass der Zeitplan das macht send_view_count_report Task wird jede Minute entsprechend dem Setup ausgeführt. Es eignet sich gut zum Testen, wird jedoch nicht für eine reale Webanwendung empfohlen.

Aufgaben zuverlässiger machen

Aufgaben werden häufig verwendet, um unzuverlässige Vorgänge auszuführen, Vorgänge, die von externen Ressourcen abhängig sind oder aus verschiedenen Gründen leicht fehlschlagen können. Hier ist eine Richtlinie, um sie zuverlässiger zu machen:

  • Machen Sie Aufgaben idempotent. Eine idempotente Aufgabe ist eine Aufgabe, die den Status des Systems in keiner Weise ändert, wenn sie auf halbem Weg angehalten wird. Die Aufgabe nimmt entweder vollständige oder keine Änderungen am System vor.
  • Wiederholen Sie die Aufgaben. Wenn die Aufgabe fehlschlägt, sollten Sie sie immer wieder versuchen, bis sie erfolgreich ausgeführt wurde. Sie können dies in Sellerie mit Celery Retry tun. Eine andere interessante Sache ist der Exponential Backoff-Algorithmus. Dies kann sich als nützlich erweisen, wenn Sie sich überlegen, unnötige Serverlast von wiederholten Aufgaben zu begrenzen.

Schlussfolgerungen

Ich hoffe, es war ein interessantes Tutorial für Sie und eine gute Einführung in die Verwendung von Sellerie mit Django. 

Hier einige Schlussfolgerungen, die wir ziehen können:

  • Es empfiehlt sich, unzuverlässige und zeitaufwändige Aufgaben außerhalb der Anforderungszeit aufzubewahren.
  • Langfristige Aufgaben sollten im Hintergrund von Arbeitsprozessen (oder anderen Paradigmen) ausgeführt werden.
  • Hintergrundaufgaben können für verschiedene Aufgaben verwendet werden, die für die grundlegende Funktionsweise der Anwendung nicht kritisch sind.
  • Sellerie kann auch periodische Aufgaben mit der Sellerie schlagen Bedienung.
  • Aufgaben können zuverlässiger sein, wenn sie idempotent gemacht und erneut versucht werden (möglicherweise mithilfe von exponentiellem Backoff).