- Funktionen
- Pricing

Dieser Blogbeitrag basiert auf einer Produktpräsentation von Antonis Kalipetis, Staff Engineer bei SymfonyCon 2023, über die Erfahrungen von Upsun mit Nix. Wir haben ChatGPT für die Transkription und zur Verbesserung der Grammatik und Syntax verwendet.
Django-Bereitstellungen haben sich seit den Anfängen des Frameworks weiterentwickelt. Während Django-Migrationen in Version 1.6 eingeführt wurden, um uns das Leben zu erleichtern, haben moderne Bereitstellungsmuster wie rollierende Updates und horizontale Skalierung neue Komplexitäten mit sich gebracht, die Entwickler verstehen und einplanen müssen. In einem Live-Workshop ging Antonis darauf ein, was bei Bereitstellungen tatsächlich schiefgehen kann und wie man dies verhindern kann.
Jede Django-Anwendungsbereitstellung besteht aus mehreren Schlüsselkomponenten, die zusammenarbeiten. An vorderster Front befindet sich ein Proxy-Server – in der Regel Nginx, Apache oder neuere Optionen wie Caddy und Traefik. Dieser Proxy übernimmt die TLS-Terminierung, das Domain-Routing und die Weiterleitungen. Dahinter befindet sich Ihr Anwendungsserver, in der Regel Gunicorn oder Uvicorn für asynchrone Anwendungen. Diese werden durch eine Cache-Schicht (wie Redis oder Memcached) und eine Datenbank (PostgreSQL, MySQL oder zunehmend SQLite für bestimmte Anwendungsfälle) unterstützt.
Diese Architektur eignet sich gut für Single-Server-Bereitstellungen, aber moderne Anwendungen laufen oft auf mehreren Servern mit rollierenden Updates, was zu Szenarien führt, in denen verschiedene Versionen Ihrer Anwendung gleichzeitig ausgeführt werden.
Wenn Sie Django-Anwendungen lokal entwickeln, übernimmt manage.py runserver automatisch die Bereitstellung statischer Dateien. In der Produktivumgebung wird dieser Ansatz jedoch problematisch. Python-Anwendungsserver sind so konzipiert, dass sie jeweils nur eine Anfrage gleichzeitig bearbeiten können (mit einigen Ausnahmen für ASGI), wodurch sie für die Bereitstellung statischer Inhalte wie CSS, JavaScript und Bilder ungeeignet sind.
Die eigentliche Herausforderung entsteht, wenn mehrere Anwendungsserver unterschiedliche Versionen Ihres Codes ausführen. Stellen Sie sich folgendes Szenario vor: Sie aktualisieren Ihr CSS mit einer neuen Markenfarben und stellen es mit Djangos „ManifestStaticFilesStorage” bereit. Dieses Speicher-Backend erstellt gehashte Dateinamen wie app.a1b2c3d4.css, um permanentes Caching zu ermöglichen.
Während einer rollierenden Bereitstellung könnte Folgendes passieren:
app.old123.css“app.new456.css“ ausWenn die Anfrage eines Benutzers nach der neuen CSS-Datei an den alten Server weitergeleitet wird, erhält er einen 404-Fehler, wodurch das Seitenlayout beschädigt wird.
Externer Speicher: Laden Sie statische Dateien auf Dienste wie Amazon S3 oder ähnliche cloud-Speicher hoch. Dadurch wird sichergestellt, dass alle Versionen Ihrer Anwendung auf dieselben statischen Dateien zugreifen können.
Caching auf Proxy-Ebene: Konfigurieren Sie Ihren Proxy-Server (Nginx usw.) so, dass statische Dateien für einen angemessenen Zeitraum zwischengespeichert werden. Dadurch entsteht während der Bereitstellung ein Puffer, in dem alte Dateien verfügbar bleiben, während neue Dateien übertragen werden.
Gemeinsam genutzte Dateisysteme: Binden Sie das statische Verzeichnis auf allen Servern ein, damit sowohl alte als auch neue Anwendungsversionen Dateien vom selben Speicherort aus bereitstellen können.
WhiteNoise-Middleware: Diese Python-Bibliothek stellt statische Dateien direkt aus Ihrer Django-Anwendung mit effizienten Caching-Headern bereit, nutzt jedoch Ressourcen des Anwendungsservers.
Django-Migrationen sind leistungsstark, erfordern jedoch in Umgebungen mit mehreren Versionen eine sorgfältige Planung. Der Referent demonstrierte dies anhand eines praktischen Beispiels mit einer Anwendung zur Meldung von Bigfoot-Sichtungen.
Das Hinzufügen eines neuen Feldes zu einem Modell scheint einfach zu sein, aber bedenken Sie, was passiert, wenn Sie ein Pflichtfeld mit einem Standardwert hinzufügen:
# New field added
gdpr_accepted = models.BooleanField(default=False)Nach der Ausführung der Migrationen erkennt die neue Anwendungsversion dieses Feld, die alte Version jedoch nicht. Wenn die alte Version versucht, einen Datensatz zu speichern, schlägt dies fehl, da die Datenbank das Feld „gdpr_accepted ” erwartet, der alte Code dieses jedoch nicht bereitstellt.
Der Referent hob den neuen Parameter „db_default” von Django 5 als Lösung hervor:
gdpr_accepted = models.BooleanField(db_default=False)Mit „db_default” verarbeitet die Datenbank selbst den Standardwert, nicht der Python-Code. Das bedeutet, dass alte Anwendungsversionen Datensätze auch ohne Kenntnis des neuen Feldes erfolgreich speichern können.
Rolling Updates führen zu einem vorübergehenden Zustand, in dem mehrere Versionen Ihrer Anwendung gleichzeitig ausgeführt werden. Dies erfordert eine sorgfältige Koordination zwischen:
Während Django das Zurücksetzen von Migrationen mit „manage.py migrate app_name 0001” einfach erscheinen lässt, sind Rollbacks in der Produktivumgebung selten so unkompliziert. Der Referent betonte aus Erfahrung, dass Rollbacks oft mit unerwarteten Problemen verbunden sind, sodass eine sorgfältige Planung zur Vorbeugung wertvoller ist als das Verlassen auf Rollback-Funktionen.
Moderne Platform-as-a-Service-Anbieter wie Upsun begegnen vielen dieser Herausforderungen durch:
Das Verständnis der zugrunde liegenden Herausforderungen bleibt jedoch auch bei der Verwendung verwalteter Plattformen von entscheidender Bedeutung.
Die integrierten Tools von Django, wie Migrationen und die Verwaltung statischer Dateien, sind leistungsstark, erfordern jedoch eine sorgfältige Anwendung in der Produktivumgebung. Die Komplexität steigt erheblich, wenn Sie von Einzelserver-Bereitstellungen zu horizontal skalierten, kontinuierlich bereitgestellten Anwendungen übergehen.
Erfolg erfordert:
Da Django-Anwendungen wachsen und Bereitstellungsmuster immer komplexer werden, müssen Entwickler ihr Verständnis über lokale Entwicklungsmuster hinaus erweitern. Das Framework stellt die Tools zur Verfügung, aber erfolgreiche Produktionsbereitstellungen erfordern eine sorgfältige Orchestrierung dieser Tools innerhalb Ihres spezifischen Infrastrukturkontexts.
Während Django unsere Entwicklungsarbeit weiterhin erleichtert, bleibt die Produktionsbereitstellung ein Bereich, in dem sorgfältige Planung und Verständnis der zugrunde liegenden Systeme sich in Bezug auf Anwendungszuverlässigkeit und Benutzererfahrung auszahlen.
Join our monthly newsletter
Compliant and validated