Jak platformy internetowe Python, WSGI i CGI pasują do siebie

150

Mam konto Bluehost, na którym mogę uruchamiać skrypty Pythona jako CGI. Myślę, że to najprostsze CGI, ponieważ aby uruchomić, muszę zdefiniować następujące elementy .htaccess:

Options +ExecCGI
AddType text/html py
AddHandler cgi-script .py

Teraz, gdy patrzę na programowanie internetowe w Pythonie, słyszę dużo o WSGI i tym, jak większość frameworków go używa. Ale po prostu nie rozumiem, jak to wszystko do siebie pasuje, zwłaszcza gdy podany jest mój serwer WWW (Apache działa na maszynie hosta) i nie jest to coś, z czym naprawdę mogę się bawić (z wyjątkiem definiowania .htaccesspoleceń).

Jak są połączone WSGI , CGI i frameworki? Co muszę wiedzieć, zainstalować i zrobić, jeśli chcę uruchomić framework sieciowy (na przykład web.py lub CherryPy ) na mojej podstawowej konfiguracji CGI? Jak zainstalować obsługę WSGI?

Eli Bendersky
źródło

Odpowiedzi:

242

Jak WSGI, CGI i frameworki są połączone?

Apache nasłuchuje na porcie 80. Otrzymuje żądanie HTTP. Analizuje żądanie, aby znaleźć sposób odpowiedzi. Apache ma DUŻO możliwości odpowiedzi. Jednym ze sposobów odpowiedzi jest użycie CGI do uruchomienia skryptu. Innym sposobem odpowiedzi jest po prostu podanie pliku.

W przypadku CGI Apache przygotowuje środowisko i wywołuje skrypt poprzez protokół CGI. Jest to standardowa sytuacja Unix Fork / Exec - podproces CGI dziedziczy środowisko systemu operacyjnego, w tym gniazdo i standardowe wyjście. Podproces CGI zapisuje odpowiedź, która wraca do Apache; Apache wysyła tę odpowiedź do przeglądarki.

CGI jest prymitywne i denerwujące. Głównie dlatego, że forkuje podproces dla każdego żądania, a podproces musi zakończyć lub zamknąć standardowe wyjście i stderr, aby oznaczyć koniec odpowiedzi.

WSGI to interfejs oparty na wzorcu projektowym CGI. Niekoniecznie jest to CGI - nie musi forkaować podprocesu dla każdego żądania. Może to być CGI, ale nie musi.

WSGI dodaje do wzorca projektowego CGI na kilka ważnych sposobów. Analizuje nagłówki żądań HTTP i dodaje je do środowiska. Dostarcza dowolne dane wejściowe zorientowane na POST jako obiekt podobny do pliku w środowisku. Zapewnia również funkcję, która sformułuje odpowiedź, oszczędzając wiele szczegółów dotyczących formatowania.

Co muszę wiedzieć / zainstalować / zrobić, jeśli chcę uruchomić framework sieciowy (powiedzmy web.py lub cherrypy) na mojej podstawowej konfiguracji CGI?

Przypomnij sobie, że rozwidlanie podprocesu jest kosztowne. Istnieją dwa sposoby obejścia tego problemu.

  1. Osadzony mod_wsgi lub osadzonymod_python Python w Apache; żaden proces nie jest rozwidlony. Apache uruchamia aplikację Django bezpośrednio.

  2. Demon mod_wsgi lub mod_fastcgipozwala Apache na interakcję z oddzielnym demonem (lub „długotrwałym procesem”) przy użyciu protokołu WSGI. Rozpoczynasz swój długotrwały proces Django, a następnie konfigurujesz mod_fastcgi Apache do komunikacji z tym procesem.

Zauważ, że mod_wsgimoże działać w obu trybach: osadzony lub demon.

Kiedy czytasz o mod_fastcgi, zobaczysz, że Django używa flup do stworzenia interfejsu kompatybilnego z WSGI na podstawie informacji dostarczonych przez mod_fastcgi. Rurociąg działa w ten sposób.

Apache -> mod_fastcgi -> FLUP (via FastCGI protocol) -> Django (via WSGI protocol)

Django ma kilka "django.core.handlers" dla różnych interfejsów.

Dla mod_fastcgi, Django zapewnia manage.py runfcgiintegrację FLUP i handler.

W przypadku mod_wsgi istnieje do tego podstawowy program obsługi.

Jak zainstalować obsługę WSGI?

Postępuj zgodnie z tymi instrukcjami.

https://code.google.com/archive/p/modwsgi/wikis/IntegrationWithDjango.wiki

W tle zobacz to

http://docs.djangoproject.com/en/dev/howto/deployment/#howto-deployment-index

S.Lott
źródło
4
Nie mogę zainstalować mod_wsgi, ponieważ korzystam z hostingu współdzielonego. Wszystko, co mam, to obsługa fcgi. Jak mogę nadal uruchamiać za jego pośrednictwem aplikacje WSGI?
Eli Bendersky
3
+1 To doskonała odpowiedź i odpowiedzi na wiele (ale nie wszystkie) pytań, które mam na myśli. Ta odpowiedź wciąż nie jest kompletna. Dobrze wyjaśniłeś CGI i WSGI, ale jaki jest związek i różnice między FASTCGI i WSGI? Co jest lepsze? Jak oni pracują? Jak pojawił się mod_python?
pazury
14
S.Lott, zamiast narzekać, kiedy ludzie pytają, co jest „lepsze”, dlaczego nie po prostu stwierdzić, że „mod_wsgi jest lepsze jak X, fastcgi jest lepsze dla Y”, a jeśli OP ma bardziej szczegółowe pytania, zada.
Gregg Lind
7
@Greg Lind: Dlaczego nie po prostu stwierdzić, że „mod_wsgi jest lepsze jak X, fastcgi jest lepsze dla Y”? Ponieważ nie jest to łatwe. Istnieją dziesiątki niefunkcjonalnych czynników jakościowych, które są elementami zbiorów X i Y. Trudno je wszystkie wymienić. O wiele lepiej jest, gdy ludzie zadają konkretne pytania dotyczące istotnych czynników jakości.
S.Lott
4
Uwaga: opcja runfcgi jest przestarzała, ponieważ wersja 1.7, a obsługa FastCGI została usunięta w Django 1.9.
OBu
58

Myślę, że odpowiedź Floriana odpowiada na część twojego pytania o "czym jest WSGI", zwłaszcza jeśli czytasz PEP .

Jeśli chodzi o pytania, które zadajesz pod koniec:

WSGI, CGI, FastCGI itp. Są protokołami dla serwera WWW do uruchamiania kodu i dostarczania tworzonej dynamicznej treści. Porównaj to ze statycznym serwowaniem internetowym, w którym zwykły plik HTML jest zasadniczo dostarczany klientowi w takiej postaci, w jakiej jest.

CGI, FastCGI i SCGI są niezależne od języka. Możesz pisać skrypty CGI w Perlu, Pythonie, C, bash, cokolwiek. CGI określa, który plik wykonywalny zostanie wywołany na podstawie adresu URL i jak będzie nazywany: argumenty i środowisko. Definiuje również, w jaki sposób wartość zwracana powinna zostać przesłana z powrotem do serwera WWW po zakończeniu działania pliku wykonywalnego. Wariacje są w zasadzie optymalizacjami, aby móc obsłużyć więcej żądań, zmniejszyć opóźnienia i tak dalej; podstawowa koncepcja jest taka sama.

WSGI to tylko Python. Zamiast protokołu niezależnego od języka zdefiniowano standardową sygnaturę funkcji:

def simple_app(environ, start_response):
    """Simplest possible application object"""
    status = '200 OK'
    response_headers = [('Content-type','text/plain')]
    start_response(status, response_headers)
    return ['Hello world!\n']

To jest pełna (jeśli jest ograniczona) aplikacja WSGI. Serwer WWW z obsługą WSGI (taki jak Apache z mod_wsgi) może wywołać tę funkcję za każdym razem, gdy nadejdzie żądanie.

Powodem, dla którego jest to tak wspaniałe, jest to, że możemy uniknąć niechlujnego kroku konwersji z HTTP GET / POST na CGI do Pythona i z powrotem po wyjściu. To znacznie bardziej bezpośrednie, czyste i wydajne połączenie.

Znacznie ułatwia również posiadanie długotrwałych frameworków działających za serwerami WWW, jeśli wszystko, co trzeba zrobić dla żądania, to wywołanie funkcji. W przypadku zwykłego CGI musiałbyś rozpocząć cały framework dla każdego indywidualnego żądania.

Aby mieć obsługę WSGI, musisz mieć zainstalowany moduł WSGI (jak mod_wsgi ) lub użyć serwera WWW z wbudowanym WSGI (jak CherryPy ). Jeśli żadna z nich to możliwe, będziesz mógł skorzystać z mostu CGI-WSGI podany w PEP.

James Brady
źródło
3
Czyj to był głupi pomysł, aby nie uczynić języka WSGI agnostykiem? Po co więc? Równie dobrze może po prostu dostarczyć cały Python jako moduł Apache.
Salman von Abbas
2
@SalmanPK Myślę, że to tylko kompromis. Z pewnością nie jest łatwo (jeśli nie niemożliwe) stworzenie protokołu niezależnego od języka, którego można by używać, po prostu implementując funkcję w wybranym języku.
phunehehe
21

Możesz uruchomić WSGI przez CGI, jak pokazano na przykładzie Pep333 . Jednak za każdym razem, gdy pojawia się żądanie, uruchamiany jest nowy interpreter Pythona i cały kontekst (połączenia z bazą danych itp.) Musi zostać zbudowany, co wymaga czasu.

Najlepiej, jeśli chcesz uruchomić WSGI, jeśli twój host zainstaluje mod_wsgi i skonfiguruje odpowiednią konfigurację, aby odroczyć kontrolę do twojej aplikacji.

Flup to kolejny sposób na uruchomienie z WSGI dla dowolnego serwera WWW, który może mówić w języku FCGI , SCGI lub AJP. Z mojego doświadczenia wynika, że ​​tylko FCGI naprawdę działa i może być używane w Apache albo przez mod_fastcgi, albo jeśli możesz uruchomić oddzielnego demona Pythona z mod_proxy_fcgi .

WSGI jest protokołem podobnym do CGI, który definiuje zestaw reguł interakcji serwera WWW i kodu Pythona, jest zdefiniowany jako Pep333 . Dzięki temu wiele różnych serwerów WWW może korzystać z wielu różnych struktur i aplikacji korzystających z tego samego protokołu aplikacji. Jest to bardzo korzystne i bardzo przydatne.

Florian Bösch
źródło
3
Czy uruchamianie WSGI przez CGI jest do czego służy "flup"? W jaki sposób flup jest połączony ze schematem?
Eli Bendersky
7

Jeśli nie masz jasności co do wszystkich terminów w tym miejscu, i spójrzmy prawdzie w oczy, jest to mylące, pełne akronimów, istnieje również dobry czytnik tła w postaci oficjalnego Pythona HOWTO, w którym omówiono CGI, FastCGI i WSGI, i tak dalej na: http://docs.python.org/howto/webservers.html

Richard Boardman
źródło
2
Adres URL jest nieaktualny, myślę, że ten jest zaktualizowany: docs.python.org/2.7/howto/webservers.html
Stefaan,
Świetny materiał :) Należy przeczytać to oficjalne wprowadzenie wraz z zaakceptowaną odpowiedzią.
Rick
4

Jest to prosta warstwa abstrakcji dla Pythona, podobna do specyfikacji Servlet dla Javy. Podczas gdy CGI jest naprawdę niskiego poziomu i po prostu zrzuca rzeczy do środowiska procesu i standardowe wejścia / wyjścia, powyższe dwie specyfikacje modelują żądanie http i odpowiedź jako konstrukcje w języku. Mam jednak wrażenie, że w Pythonie ludzie nie do końca zdecydowali się na de facto implementacje, więc masz mieszankę implementacji referencyjnych i innych bibliotek narzędziowych, które zapewniają inne rzeczy wraz z obsługą WSGI (np. Wklej). Oczywiście mogę się mylić, jestem nowicjuszem w Pythonie. Społeczność „skryptów internetowych” podchodzi do problemu z innej strony (hosting współdzielony, dziedzictwo CGI,

aaron
źródło