Warum brauche ich Nginx und so etwas wie Gunicorn?


219

Ich suche eine zu vereinfachte Antwort auf die folgende Frage. Ich versuche, ein grundlegendes Verständnis dafür zu entwickeln, wie Nginx neben etwas wie Gunicorn funktioniert.

Benötige ich sowohl Nginx als auch etwas wie Gunicorn, um Django-Apps auf Nginx bereitzustellen?

Wenn ja, wie werden die HTTP-Anforderungen tatsächlich behandelt?

Ps. Ich möchte Apache und mod_wsgi nicht benutzen!


Apache und mod_wsgi sind die einfachste Methode, um die Brücke zwischen Ihrer Django-Anwendung und HTTP-Anforderungen zu implementieren, die auch in einer Produktionsumgebung sehr leistungsfähig ist. Für viele Entwickler bedeutet dies, dass "Apache besser als Nginx" ist, wenn sie es nur wussten, aber da "Betamax besser als VHS" ist, herrscht leider Dogma
MagicLAMP

Antworten:


314

Übermäßig vereinfacht: Sie benötigen etwas, das Python ausführt, aber Python kann nicht alle Arten von Anforderungen am besten verarbeiten.

[Haftungsausschluss: Ich bin ein Gunicorn-Entwickler]

Weniger vereinfacht: Unabhängig davon, welchen App-Server Sie verwenden (Gunicorn, mod_wsgi, mod_uwsgi, cherrypy), hat jede Art von nicht-trivialer Bereitstellung einen Upstream, der die Anforderungen verarbeitet, die Ihre Django-App nicht verarbeiten sollte. Triviale Beispiele für solche Anforderungen sind die Bereitstellung statischer Elemente (images / css / js).

Dies führt zu zwei ersten Ebenen der klassischen "dreistufigen Architektur". Das heißt, der Webserver (in Ihrem Fall Nginx) verarbeitet viele Anfragen nach Bildern und statischen Ressourcen. Anforderungen, die dynamisch generiert werden müssen, werden dann an den Anwendungsserver (in Ihrem Beispiel Gunicorn) weitergeleitet. (Abgesehen davon ist die dritte der drei Ebenen die Datenbank)

Historisch gesehen würde jede dieser Ebenen auf separaten Maschinen gehostet (und es würde höchstwahrscheinlich mehrere Maschinen in den ersten beiden Ebenen geben, dh: 5 Webserver senden Anforderungen an zwei App-Server, die wiederum eine einzelne Datenbank abfragen).

In der Neuzeit haben wir jetzt Anwendungen in allen Formen und Größen. Nicht jedes Wochenendprojekt oder jede Website für kleine Unternehmen benötigt die Leistung mehrerer Maschinen und kann problemlos auf einer einzigen Box ausgeführt werden. Dies hat zu neuen Einträgen in die Reihe der Hosting-Lösungen geführt. Einige Lösungen verbinden den App-Server mit dem Webserver (Apache httpd + mod_wsgi, Nginx + mod_uwsgi usw.). Und es ist keineswegs ungewöhnlich, die Datenbank auf demselben Computer wie eine dieser Web- / App-Server-Kombinationen zu hosten.

Im Fall von Gunicorn haben wir eine spezielle Entscheidung getroffen (Kopieren von Ruby's Unicorn), um die Dinge von Nginx zu trennen, während wir uns auf das Proxy-Verhalten von Nginx verlassen. Insbesondere wenn wir davon ausgehen können, dass Gunicorn niemals Verbindungen direkt aus dem Internet liest, müssen wir uns keine Sorgen um langsame Clients machen. Dies bedeutet, dass das Verarbeitungsmodell für Gunicorn peinlich einfach ist.

Durch die Trennung kann Gunicorn auch in reinem Python geschrieben werden, wodurch die Entwicklungskosten minimiert und die Leistung nicht wesentlich beeinträchtigt werden. Außerdem können Benutzer andere Proxys verwenden (vorausgesetzt, sie puffern ordnungsgemäß).

Was Ihre zweite Frage anbelangt, was die HTTP-Anfrage tatsächlich behandelt, lautet die einfache Antwort Gunicorn. Die vollständige Antwort ist, dass sowohl Nginx als auch Gunicorn die Anfrage bearbeiten. Grundsätzlich erhält Nginx die Anfrage, und wenn es sich um eine dynamische Anfrage handelt (im Allgemeinen basierend auf URL-Mustern), gibt es diese Anfrage an Gunicorn weiter, der sie verarbeitet, und sendet dann eine Antwort an Nginx zurück, die die Antwort dann an das Original weiterleitet Klient.

Also zum Schluss ja. Sie benötigen sowohl Nginx als auch Gunicorn (oder etwas Ähnliches) für eine ordnungsgemäße Django-Bereitstellung. Wenn Sie speziell Django mit Nginx hosten möchten, würde ich Gunicorn, mod_uwsgi und vielleicht CherryPy als Kandidaten für die Django-Seite der Dinge untersuchen.


14
Vielen Dank, dass Sie sich die Zeit genommen haben, eine so ausführliche Antwort zu schreiben! Irgendwelche Leseempfehlungen zu dieser "3-Tier-Architektur"?
Uhr

5
Gute Antwort, aber ich verstehe das Problem mit langsamen Clients nicht.
Mads Skjern

3
@MadsSkjern Ich schätze hier, aber wenn Sie davon ausgehen, dass alle Clients schnell sind, können Sie einen festen Pool von Arbeitsprozessen verwenden und müssen nicht für den Fall codieren, dass viele oder alle blockiert werden und auf einen Client warten.
Jonathan Hartley


7
meine django app dient nur json keine statischen inhalte kann ich nur mit gunicorn und no nginx gehen
Sar009

27

Mir hat diese Erklärung in ihrer Einfachheit gefallen:

Nginx wird sich der Außenwelt stellen. Es werden Mediendateien (Bilder, CSS usw.) direkt aus dem Dateisystem bereitgestellt. Es kann jedoch nicht direkt mit Django-Anwendungen kommunizieren. Es wird etwas benötigt, das die Anwendung ausführt, Anfragen aus dem Web füttert und Antworten zurückgibt.

Das ist Gunicorns Job. Gunicorn erstellt einen Unix-Socket und sendet Antworten an nginx über das wsgi-Protokoll. Der Socket leitet Daten in beide Richtungen weiter:

The outside world <-> Nginx <-> The socket <-> Gunicorn

https://gist.github.com/Atem18/4696071


Es müssen keine Steckdosen sein, nur für den Fall, dass sich andere fragen.
Akshay

0

Ich suche eine zu vereinfachte Antwort ...

Benötige ich sowohl Nginx als auch etwas wie Gunicorn, um Django-Apps auf Nginx bereitzustellen?

Wenn ja, wie werden die HTTP-Anforderungen tatsächlich behandelt?

Übermäßig vereinfachte Antwort:

JA.

Sowohl Nginx als auch Gunicorn.

Da Sie auf Nginx bereitstellen, benötigen Sie natürlich Nginx.

Da Sie Django, ein Webframework, bereitstellen, benötigen Sie eine Brücke zwischen dem Webserver (Nginx) und dem Webframework (Django). In der Python-Welt wird so etwas als WSGI-Server bezeichnet (aber denken Sie, dass es sich um eine Middleware handelt). Beispiele hierfür sind Gunicorn und uWSGI. Bei der Bearbeitung einer Anfrage leitet Nginx die Anfrage als Proxy an Gunicorn oder uWSGI weiter, der wiederum Django-Code aufruft und die Antwort zurückgibt.

Dieses Dokument und die Antwort von Paulus helfen Ihnen dabei, es besser zu lernen.


0

Gunicorn ist eine Verschwendung von Ressourcen. Sie können einfach einen Proxy-Pass an Django übergeben, indem Sie einen Port abhören, anstatt Gunicorn auf Django und erneut Nginx auf all dem laufen zu lassen. Bei den Benchmarks habe ich einen sehr deutlichen Geschwindigkeitsanstieg gesehen. Nginx kann problemlos direkte Anfragen an Django bearbeiten. Gunicorn ist nichts anderes als eine Überführung (eigentlich eine langsamere Überführung) über der normalen Straße. Es sitzt und frisst nur Ihre Ressourcen und versucht zu behaupten, Ihre Website mit Strom zu versorgen.

nginx puffert grundsätzlich alle Anfragen und bearbeitet die statischen Dateianfragen selbst (wenn Sie es so konfiguriert haben). Und überträgt den gesamten dynamischen Inhalt an einen anderen Server (Gunicorn / Django).

Gunicorn hat keine andere Verwendung als nur die Anfrage an die Anwendung weiterzuleiten. Es ist wie bei einem Strohhalm, den man direkt aus dem Glas oder in begrenztem Tempo aus dem Strohhalm trinken kann (hier ist der Trinkende Django). Und Nginx ist der Kellner, der Ihnen das Glas Saft gebracht hat.

Ich habe dies verglichen und festgestellt - mit Gunicorn: 22k req / s ohne Gunicorn: 34k req / s

Ihre Site benötigt die zusätzlichen Anforderungen bei hoher Auslastung.


1
Sprechen Sie über das Ausführen des Entwicklungsservers in der Produktion ?!
Michael Hampton

Der Entwicklungsserver kann hinter einem Produktionsserver (wie nginx) ausgeführt werden. Weil die Anfragen an der richtigen Stelle eingehen und Sicherheit und Effizienz vom Produktionsserver übernommen werden. Es ist so, als würde man nur eine WSGI + Flasche verwenden. Stattdessen können Sie nur Nginx + Django verwenden (ohne Middleware-Hogging wie Gunicorn). Bitte testen Sie das Setup unter Last und Sie werden es verstehen.
ShadowDoom

1
github.com/django/channels/issues/142 (TLDR: seine schlechte Idee)
igor
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.