>_ DevTrendsde

Sprache

Start

Sprachen

Bereiche

Frontend Backend Mobile DevOps AI / ML GameDev Blockchain Embedded Sicherheit
Python

Aufgaben in Python ohne Celery planen und Workarounds

Jeder Backend-Entwickler hat wahrscheinlich schon einmal damit zu tun gehabt. Sie bauen einen Web-Service mit FastAPI oder Flask auf, das Projekt ist noch klein und läuft auf einem einzelnen Server. Dann fragt der Product Manager: "Hey, lass uns den Kunden jeden Morgen um 9 Uhr einen Newsletter schicken und abgelaufene Warenkörbe stündlich zurücksetzen?"

Der erste Instinkt ist, Celery mit Celery Beat und Redis anzubinden. Aber einen Broker hochzufahren, Worker zu konfigurieren und Daemons zu überwachen, nur für zwei Hintergrundaufgaben, fühlt sich übertrieben an. Die zweite Option ist System-Cron, aber das verteilt die Logik über Anwendungscode und Server-Konfiguration. Sie möchten den Scheduler in Ihrem Code eingebettet haben, der asyncio verarbeiten kann und bei Bedarf auf mehrere Knoten skaliert.

Hier kommt die APScheduler (Advanced Python Scheduler) Bibliothek zum Einsatz.

Was die Bibliothek leisten kann

APScheduler gibt es schon eine Weile, und das Projekt befindet sich derzeit im Übergang zu Version 4.0. Der vierte Branch befindet sich noch im Pre-Release-Status, hat aber die Architektur der Bibliothek erheblich umstrukturiert.

Zuvor war es hauptsächlich ein lokaler Scheduler für einen einzelnen Prozess, aber jetzt hat sich das Tool zu einem vollständigen verteilten Queue- und Planungssystem entwickelt. Der einfachste Anwendungsfall läuft immer noch in nur drei Zeilen Code.

Das Kernkonzept: Sie deklarieren reguläre Python-Funktionen oder Coroutines und hängen einen Trigger mit den notwendigen Ausführungsbedingungen an.

from apscheduler.schedulers.asyncio import AsyncIOScheduler

scheduler = AsyncIOScheduler()

async def send_digest():
    print("Отправляем утренний дайджест...")

# Запуск каждый будний день в 9 утра
scheduler.add_job(send_digest, 'cron', day_of_week='mon-fri', hour=9, minute=0)
scheduler.start()

Die Bibliothek übernimmt die Zeitverfolgung, berechnet Offsets und ruft Funktionen zum richtigen Zeitpunkt auf.

Planungsoptionen

Vier eingebaute Trigger-Typen sind verfügbar:

  • Cron-Trigger. Vertraute Linux-artige Syntax. Sie können flexibel Wochentage, Monate, bestimmte Stunden und Minuten festlegen.
  • Intervalle. Ausführung alle N Sekunden, Minuten oder Stunden. Nützlich für regelmäßiges Polling externer APIs.
  • Kalender-Trigger. Benötigt, wenn das Intervall von der Länge eines Monats oder Jahres abhängt. Zum Beispiel eine Aufgabe strikt am ersten Tag jedes Monats um 12 Uhr ausführen.
  • Einmalige Ausführung. Wird genau einmal zu einem bestimmten zukünftigen Datum und Zeitpunkt ausgelöst.

Wenn die eingebauten Bedingungen nicht ausreichen, können Trigger mit zusammengesetzten Regeln kombiniert oder Sie können Ihre eigene Klasse mit eigener Logik schreiben.

Schutz vor häufigen Ausfällen

In der Praxis stoßen Hintergrundaufgaben regelmäßig auf Überlastungen und Verzögerungen. APScheduler enthält mehrere nützliche Mechanismen, die in benutzerdefinierten Lösungen auf Basis von while True und sleep oft übersehen werden.

Erstens die Begrenzung gleichzeitiger Ausführungen. Wenn Sie einen schweren Berichtsexport alle fünf Minuten konfiguriert haben, aber der vorherige Lauf sieben Minuten hängengeblieben ist, startet der Scheduler keine zweite Instanz parallel und überlastet nicht die Datenbank.

Zweitens der jitter Parameter. Er fügt eine zufällige Verzögerung zur Startzeit der Aufgabe hinzu. Stellen Sie sich vor, Sie haben hundert Worker, und sie müssen alle den Cache genau um 00:00 aktualisieren. Ohne Jitter erhält die Datenbank einen sofortigen Lastspitzen. Mit einem zufälligen Offset von ein paar Sekunden wird die Last gleichmäßig verteilt.

Drittens die Behandlung der Misfire Grace Time. Wenn der Server unter Last eingefroren ist oder neu gestartet wurde, prüft der Scheduler, wie stark die Aufgabe in Verzug geraten ist. Wenn die Verzögerung innerhalb des akzeptablen Limits liegt, wird die Aufgabe ausgeführt; wenn nicht, wird sie übersprungen, ohne dass sich eine Queue aufbaut.

Speicherung und verteilter Modus

Für einfache Skripte können Aufgaben im Speicher gehalten werden. Aber wenn der Service neu startet, wird der Zeitplan zurückgesetzt. Um dies zu vermeiden, unterstützt die Bibliothek persistente Speicherung:

  • PostgreSQL
  • MySQL
  • SQLite
  • MongoDB

In Version vier hat der Scheduler gelernt, in einem verteilten Cluster zu arbeiten. Mehrere Anwendungsinstanzen verbinden sich mit einer gemeinsamen Datenbank und einem Event-Broker (Redis, PostgreSQL LISTEN/NOTIFY und MQTT werden unterstützt).

Dadurch wird horizontale Skalierung erreicht: Ein Knoten fällt aus, die anderen übernehmen die Aufgaben aus der Queue.

# Пример концепции работы с постоянным хранилищем
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore

jobstores = {
    'default': SQLAlchemyJobStore(url='postgresql+asyncpg://user:pass@localhost/mydb')
}

scheduler = AsyncIOScheduler(jobstores=jobstores)

Synchroner und asynchroner Code

Die Bibliothek fügt sich gut in den modernen Python-Stack ein. Es sind verschiedene Scheduler-Implementierungen verfügbar:

  • AsyncIOScheduler und Integration mit Trio für moderne Async-Backends wie FastAPI, Litestar oder Aiohttp.
  • BackgroundScheduler und BlockingScheduler für synchrone Skripte, Django und Flask.

Sie müssen Async-Funktionen nicht mit asyncio.run() in synchronen Workarounds wrappen – der Scheduler awaited Coroutines nativ innerhalb der Hauptereignisschleife.

Wo dies nützlich ist

Ich greife normalerweise in drei typischen Situationen zu APScheduler:

  1. Kleine Microservices und Bots. Wenn der Einsatz von Celery oder RQ übertrieben wäre und periodische Aufgaben direkt im Prozess benötigt werden.
  2. Verzögerte Benutzeraktionen. Zum Beispiel eine E-Mail senden, in der der Benutzer gebeten wird, eine Bestellung genau 24 Stunden nach Lieferung zu bewerten.
  3. Bereinigung temporärer Daten und periodische Synchronisation von Referenzdaten aus externen Systemen.

Lohnt sich der Einsatz in einem Projekt

Wenn Sie in Python schreiben und vorhersehbare zeitbasierte Aufgabenausführung benötigen, ist APScheduler eine der ausgereiftesten Optionen.

Der einzige Punkt gerade jetzt: Die Übergangsphase zwischen den Versionen 3.x und 4.0. Der dritte Branch ist seit Jahren in der Produktion getestet, ist maximal stabil, hat aber Einschränkungen im verteilten Betrieb. Version 4.0 bringt moderne Architektur und Skalierung, aber der Autor warnt ehrlich vor möglichen Breaking API-Änderungen vor dem endgültigen Release.

Für die aktuelle Produktion ist es sicherer, beim stabilen 3.x Branch zu bleiben, und Version 4.0 lohnt sich, in privaten Projekten oder neuen Microservices auszuprobieren, während Sie die kommenden Änderungen im Auge behalten.

Ähnliche Projekte