Dlaczego potrzebuję Nginx i czegoś takiego jak Gunicorn?

219

Szukam zbyt uproszczonej odpowiedzi na następujące pytanie. Próbuję zbudować fundamentalne zrozumienie, w jaki sposób Nginx działa obok czegoś takiego jak Gunicorn.

Czy potrzebuję zarówno Nginx, jak i Gunicorn do wdrażania aplikacji Django na Nginx?

Jeśli tak, co faktycznie obsługuje żądania HTTP?

Ps. Nie chcę używać Apache i mod_wsgi!

jestem
źródło
Apache i mod_wsgi to najprostszy sposób implementacji pomostu między aplikacją django a żądaniami HTTP, który jest również bardzo wydajny w środowisku produkcyjnym. Dla wielu programistów oznacza to, że „Apache jest lepszy niż nginx”, jeśli wie, ale o tym wie, ale ponieważ „betamax jest lepszy niż VHS”, niestety zasady Dogma
MagicLAMP

Odpowiedzi:

314

Zbyt uproszczone: potrzebujesz czegoś, co uruchamia Pythona, ale Python nie jest najlepszy w obsłudze wszystkich typów żądań.

[zastrzeżenie: Jestem programistą Gunicorn]

Mniej uproszczone: Niezależnie od tego, jakiego serwera aplikacji używasz (Gunicorn, mod_wsgi, mod_uwsgi, cherrypy), każde nietrywialne wdrożenie będzie miało coś upstream, który obsłuży żądania, których twoja aplikacja Django nie powinna obsługiwać. Trywialnymi przykładami takich żądań są zasoby statyczne (images / css / js).

Powoduje to powstanie dwóch pierwszych poziomów klasycznej „architektury trzypoziomowej”. Tzn. Serwer WWW (w twoim przypadku Nginx) obsłuży wiele żądań obrazów i zasobów statycznych. Żądania, które muszą być generowane dynamicznie, zostaną następnie przekazane do serwera aplikacji (w Twoim przykładzie Gunicorn). (Nawiasem mówiąc, trzeci z trzech poziomów to baza danych)

Historycznie rzecz biorąc, każda z tych warstw byłaby hostowana na osobnych komputerach (i najprawdopodobniej w dwóch pierwszych warstwach byłoby wiele komputerów, tj .: 5 serwerów WWW wysyła żądania do dwóch serwerów aplikacji, które z kolei odpytują jedną bazę danych).

W erze współczesnej mamy teraz aplikacje wszystkich kształtów i rozmiarów. Nie w każdy weekendowy projekt lub strona małej firmy faktycznie potrzebuje mocy wielu maszyn i będzie działać całkiem szczęśliwie na jednym pudełku. Spowodowało to pojawienie się nowych wpisów w szeregu rozwiązań hostingowych. Niektóre rozwiązania będą łączyć serwer aplikacji z serwerem WWW (Apache httpd + mod_wsgi, Nginx + mod_uwsgi itp.). I wcale nie jest rzadkością hostowanie bazy danych na tym samym komputerze, co jedna z tych kombinacji serwera WWW / aplikacji.

Teraz w przypadku Gunicorn podjęliśmy konkretną decyzję (kopiowanie z Unicorn Ruby), aby oddzielić rzeczy od Nginx, polegając na zachowaniu proxy Nginx. W szczególności, jeśli możemy założyć, że Gunicorn nigdy nie będzie czytać połączeń bezpośrednio z Internetu, nie musimy martwić się o klientów, którzy działają wolno. Oznacza to, że model przetwarzania dla Gunicorn jest krępująco prosty.

Rozdzielenie pozwala również na pisanie Gunicorn w czystym Pythonie, co minimalizuje koszty rozwoju, ale nie wpływa znacząco na wydajność. Umożliwia także użytkownikom korzystanie z innych serwerów proxy (przy założeniu, że buforują poprawnie).

Jeśli chodzi o twoje drugie pytanie dotyczące tego, co faktycznie obsługuje żądanie HTTP, prostą odpowiedzią jest Gunicorn. Pełna odpowiedź brzmi: zarówno Nginx, jak i Gunicorn obsługują żądanie. Zasadniczo, Nginx otrzyma żądanie, a jeśli jest to żądanie dynamiczne (zwykle oparte na wzorcach adresów URL), wówczas przekaże to żądanie Gunicorn, który je przetworzy, a następnie zwróci odpowiedź do Nginx, który następnie przekaże odpowiedź z powrotem do oryginału klient.

A więc na zakończenie tak. Do prawidłowego wdrożenia Django potrzebujesz zarówno Nginx, jak i Gunicorn (lub czegoś podobnego). Jeśli szczególnie chcesz hostować Django z Nginx, zbadałbym Gunicorn, mod_uwsgi, a może CherryPy jako kandydatów na stronę Django.

Paul J. Davis
źródło
14
Dziękujemy za poświęcenie czasu na napisanie tak szczegółowej odpowiedzi! Czy jest jakaś rekomendowana lektura na temat „architektury trójwarstwowej”?
Jestem
5
Świetna odpowiedź, jednak nie rozumiem problemu z powolnymi klientami.
Mads Skjern
3
@MadsSkjern Zgaduję tutaj, ale jeśli zakładasz, że wszyscy klienci są szybcy, możesz użyć stałej puli procesów roboczych i nie musisz kodować na wypadek, gdy wielu lub wszystkich z nich zostanie zablokowanych w oczekiwaniu na klienta.
Jonathan Hartley,
7
moja aplikacja django obsługuje tylko JSON, bez zawartości statycznej, mogę po prostu iść z gunicorn i bez Nginx
Sar009
27

Podobało mi się to wyjaśnienie w swojej prostocie:

Nginx zmierzy się ze światem zewnętrznym. Będzie obsługiwał pliki multimedialne (obrazy, CSS itp.) Bezpośrednio z systemu plików. Nie może jednak komunikować się bezpośrednio z aplikacjami Django; potrzebuje czegoś, co uruchomi aplikację, nakarmi jej żądania z sieci i zwróci odpowiedzi.

To praca Gunicorn. Gunicorn utworzy gniazdo Unix i będzie obsługiwać odpowiedzi na nginx za pośrednictwem protokołu wsgi - gniazdo przekazuje dane w obu kierunkach:

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

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

Juuso Ohtonen
źródło
Nie muszą to być gniazda, na wypadek, gdyby inni się zastanawiali.
akshay,
0

Szukam zbyt uproszczonej odpowiedzi ...

Czy potrzebuję zarówno Nginx, jak i Gunicorn do wdrażania aplikacji Django na Nginx?

Jeśli tak, co faktycznie obsługuje żądania HTTP?

Zbyt uproszczona odpowiedź:

TAK.

Zarówno Nginx, jak i Gunicorn.

Ponieważ wdrażasz na Nginx, oczywiście potrzebujesz Nginx.

Ponieważ wdrażasz Django, który jest strukturą internetową, potrzebujesz czegoś, co pomija rozmowę między serwerem WWW (Nginx) a strukturą internetową (Django). W świecie Python takie coś nazywa się serwerem WSGI (ale myślę, że to jak oprogramowanie pośrednie), którego przykładami są Gunicorn i uWSGI. Podczas obsługi żądania Nginx przekazuje zapytanie do Gunicorn lub uWSGI, który z kolei wywołuje kod Django i zwraca odpowiedź.

Ten dokument i odpowiedź Paula pomogą ci się go lepiej nauczyć.

Cyker
źródło
0

Gunicorn to marnowanie zasobów. Możesz po prostu przekazać proxy do django nasłuchującego na porcie zamiast uruchamiać gunicorn na górnym django i ponownie nginx na tym wszystkim. W testach porównawczych zauważyłem bardzo zauważalny wzrost prędkości. Nginx może z łatwością obsługiwać bezpośrednie żądania do django. Gunicorn to nic innego jak estakada (właściwie wolniejsza estakada) nad normalną drogą. Po prostu siedzi i zjada twoje zasoby i próbuje twierdzić, że napędza twoją stronę.

nginx zasadniczo buforuje wszystkie żądania i sam obsługuje żądania plików statycznych (jeśli tak to skonfigurowałeś). I przekazuje całą dynamiczną zawartość do innego serwera. (Gunicorn / django).

Gunicorn nie ma innego zastosowania niż przekazanie wniosku do aplikacji. To jak słomka, którą możesz pić bezpośrednio ze szklanki lub pić ze słomy w ograniczonym tempie (tutaj osobą pijącą jest django). A Nginx jest kelnerem, który przyniósł ci szklankę soku.

Przeprowadziłem testy porównawcze i znalazłem to - z gunicorn: 22k req / s bez gunicorn: 34k req / s

Twoja strona będzie potrzebować dodatkowych wymagań / s przy dużym obciążeniu.

ShadowDoom
źródło
1
Czy mówisz o uruchomieniu serwera programistycznego w produkcji ?!
Michael Hampton
Serwer programistyczny można uruchomić za serwerem produkcyjnym (takim jak nginx). Ponieważ będzie otrzymywał żądania we właściwym miejscu, a bezpieczeństwo i wydajność będą obsługiwane przez serwer produkcyjny. To tak, jakby używać tylko kolby WSGI +. Zamiast tego możesz użyć po prostu nginx + django (bez zbędnego pośrednictwa, jak gunicorn). Sprawdź konfigurację przy dużym obciążeniu, a zrozumiesz.
ShadowDoom
1
github.com/django/channels/issues/142 (TLDR: to zły pomysł)
igor