In Djangos Dokumentation wird empfohlen, statische Dateien durch den Webserver ausliefern zu lassen. Was bedeutet das? Django läuft doch auf dem Webserver.

Im Prinzip geht es darum, Dateien die Django nicht bearbeiten muss, nicht durch den Django-Prozess zu schleifen. Statische Dateien sollen also den direkten Weg von der Festplatte zum Webserver finden (grüne Linie).
Das -- ich nenne es mal -- Problem ist, dass Django eine Funktion bereit stellt, statische Dateien durch Django zu schleifen: How to serve static files.

Hierbei wandern alle statischen Dateien durch den Django-Prozess anstatt dass sie direkt an den Webserver geliefert werden. Das ist ganz klar ineffizient.
Warum gibt's das dann? In erster Linie ist es für Entwickler die den Devserver nutzen gedacht und während der Entwicklung keinen zusätzlichen Webserver zum Static-Serving aufsetzen möchten.
Fazit also: Vermeide Static-Serving durch Django um jeden Preis -- es gibt natürlich Ausnahmen, siehe weiter unten.
PHP macht das doch auch so
Letzens hatte mich ein PHP-Entwickerl auch gefragt, wieso er da nicht Django nehmen kann, dass geht doch auch mit PHP.
Oberes ist ein Zitat aus dem #django-de Channel. PHP macht es aber (unbewusst) genauso wie Django. Statische Dateien werden auch direkt vom Webserver geliefert und nicht erst durch den PHP-Prozessor geschleift. Dieser verarbeitet im Normalfall nur Dateien mit der Endung .php.
Ein Static-Serving durch PHP würde etwa so aussehen, dass der Webserver ein Stylesheet mit 'GET /stylesheet.php' anfordert, und diese Datei das unten gezeigte Script ausführt.
<?php echo file_get_contents('/var/www/static/stylesheet.css'); ?>
Ziemlich dämlich, oder? Aber leider alles schon gesehen. :-(
Spezialisten
Überlasse das Static-Serving einem Server der besser dafür geeignet ist, zum Beispiel nginx oder Lighty.
Den oberen Satz hört man sehr häufig wenn es es Static-Serving geht. Was ist gemeint?
Zuerst einmal, nginx und lighttpd, oder auch liebevoll lighty genannt, sind Webserver, die auf das Ausliefern statischer Dateien optimiert sind. Dabei sind sie nicht unbedingt schneller als der Apache, ihre Stärke liegt in der Auslieferung von mehreren tausend Dateien pro Sekunde, denn dabei sind sie weniger RAM- und CPU-hungrig und skalieren besser.
Es gibt einen Weg, das beste beiden Webservern (Apache für Django, nginx für statische Dateien) herauszuholen. Dabei übernimmt nginx (oder lighty) als Frontend-Server alle Anfragen des Webbrowsers und serviert die statischen Dateien direkt. Anfragen auf dynamische Dateien werden an den Apache-Prozess weitergeleitet, der auf einem anderen Port (also nicht :80) lauscht. (Konfigurationsbeispiel)

Das Ganze ist dann schon ein recht kompliziertes Setup. Meine persönliche Meinung ist, wenn man den Punkt erreicht hat, dass ein spezialisierter Webserver für statische Dateien nötig ist, sollte man den statischen Kram auf eine eigene Maschine auslagern:

Letztendlich ist alles eine Frage des Budgets. Nicht unerwähnt soll bleiben, dass es auch Firmen gibt, die sich auf das Static-Serving spezialisiert haben. Akamai ist ein Vertreter aber auch Amazons S3 Service ist hervorragend dafür geeignet.
Was wäre wenn?
Es gibt natürlich auch das Problem, dass man statische Dateien durch Django schleifen muss. Beispiele:
-
Die Datei soll nur für bestimmte, authentifizierte User verfügbar gemacht werden.
Django stellt für solche Fälle eine Möglichkeit zur Verfügung, dass sich der Apache an Djangos Auth-Backend koppeln kann. Mehr Infos dazu in der Dokumentation. -
Die Datei wird dynamisch erzeugt, zum Beispiel ein PDF-Export der aktuellen Seite.
Vielleicht wäre hier eine Lösung, die Datei im Medienordner zu speichern und einen Location-Header zu dieser Datei zu senden. Dann übernimmt der Webserver wieder das Ausliefern der statischen Dateien und man erhält zudem ein statisches Caching der Dateien.
Jedenfalls, wenn es denn nicht anders möglich ist versuche große Dateien als Iterator an das Response-Objekt zu übergeben. Damit wird nicht die gesamte Datei in den Prozess geladen (bei einer 80MB Datei wäre der wsgi-Prozess dann 90MB+ groß) sondern in kleinen Häppchen (Chunks) durchgeschleift.
Beachte dazu aber, dass die GZip-Middleware diesen Prozess zerstören kann: Ticket #7581. Aber auch dafür gibt es eine einfache, performante Lösung. :-)
Noch ein wichtiger Nachtrag:
Auch wenn in den Bildern mod_python angegeben ist, empfehle ich euch doch ganz stark mod_wsgi als Kleber zwischen Django und Apache. Es ist resoucen schonender, performanter und allgemein sympathischer. Leider aber hat mod_wsgi kein Logo das ich benutzen konnte. ;-)
Mehr dazu
Mehr Lesestoff und vor allem Konfigurations-Beispiele für verschiedene Webserver-Szenarien findest du im deutschsprachigen django-hosting Wiki.
Martin Geber Oct. 13, 2008
Großartiger Beitrag. Ich kann steph vollkommen zustimmen.
mod_wsgi ist also wirklich besser als mod_python? Ist die Konfiguration schwieriger oder weshalb ist mod_python verbreiteter?
Viele Grüße.
Martin Oct. 13, 2008
@Martin Geber: In der alten Dokumentation war mod_python+Apache noch als die bevorzugte Umgebung angegeben. Das ist nun wirklich obsolet.
Außerdem ist mod_wsgi ja noch nicht so alt, es gibt in den meisten Distributionen schlichtweg kein (aktuelles) Paket, man muss es sich selbst kompilieren. Dass ist aber sehr einfach und schnell, da es kaum Abhängigkeiten hat.
Thomas Kerpe Oct. 16, 2008
Sehr schön!
Statische Daten für authentifizierte Benutzer lassen sich ebenfalls mit einem Nginx, Lighty, oder auch S3 ausliefern. Entweder z.B: lighties mod_secdownload bzw nginx ngx_http_accesskey_module Oder ein anderer Weg der sich gerade für die Proxy-Lösung eignet: X-Sendfile bzw x-accel-redirect hierbei wird ein direkter GET auf die jeweilige resource vom Proxy verboten, erst wenn ein Header von Django-Backend-Server gesendet wird löst dies das Senden der auf dem Proxy befindlcihen Resource aus.
Links:
Thomas Guettler Nov. 3, 2008
Hallo,
ein guter Artikel mit schönen Bildern.
Wer nicht nur Blogs liest, empfehle ich das Buch "Scalable Internet Architectures".
http://scalableinternetarchitectures.com/blog/pages/about
Anh Tu Nov. 12, 2008
Hi Martin, Du hast eine echt tolle Homepage. Gefällt mir super. Ich habe eine Frage zum Thema Django Setup bzw. zu diesem Blog Eintrag:
Da Apache (obwohl sehr etabliert) doch recht viele Ressourcen zieht, steht die Überlegung im Raum, sowohl dynamic als auch static über lighty laufen zu lassen.
Wie fändest Du das? Ist das ok oder schlägst Du als Profi die Hände über den Kopf zusammen? Würd da gerne Deine Meinung zu hören.
Viele Grüße aus Bonn, Anh Tu