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.