WSGI-протокол
Сначала проясните следующие понятия:
WSGI:полное имяWeb Server Gateway Interface,WSGIне сервер,pythonмодули, фреймворки,APIили любое программное обеспечение, просто спецификация, описывающаяweb serverКак работать сweb applicationСпецификации для связи.serverа такжеapplicationСпецификация находится вPEP 3333подробно описаны. Для реализации протокола WSGI должны быть реализованы как веб-сервер, так и веб-приложение, которые в настоящее время работают наWSGIпо соглашениюwebкадр имеетBottle, Flask, Django.
увсги:а такжеWSGIТот же протокол связи, даuWSGIЭксклюзивный протокол сервера, определяющий тип передаваемой информации (type of information),Каждыйuwsgi packetвперед4byteДля описания типа передаваемой информации это две вещи с протоколом WSGI.Говорят, что протоколfcgiВ 10 раз быстрее, чем протокол.
uWSGI:Являетсяwebсервер, реализованныйWSGIпротокол,uwsgiпротокол,httpсоглашение и др.
WSGIСоглашение в основном включаетserverа такжеapplicationДве части:
-
WSGI serverОтветственный за прием заявок от клиентов, будетrequestвперед кapplication,Будуapplicationвернутьresponseвозврат клиенту; -
WSGI applicationполученоserverперенаправленrequest, обработать запрос и вернуть результат обработки вserver.applicationможет включать промежуточное ПО с несколькими стеками (middlewares), это ПО промежуточного слоя должно реализовывать как сервер, так и приложение, поэтому они могут играть роль посредника между сервером WSGI и приложением WSGI: для сервера ПО промежуточного слоя действует как приложение, а для приложения ПО промежуточного слоя действует как сервер .
WSGIПротокол фактически определяетserverа такжеapplicationРазвязанная спецификация, т.е. может быть несколько реализацийWSGI serverсервер, также может быть несколько реализацийWSGI applicationрамка, тогда вы можете выбрать любойserverа такжеapplicationКомбинируя свои собственныеwebзаявление. НапримерuWSGIа такжеGunicornэто все реализованоWSGI serverсервер протоколов,Django,FlaskреализуетсяWSGI applicationпротоколwebФреймворк можно использовать в сочетании с реальной ситуацией проекта.
картинаDjango,FlaskФреймворк имеет собственную реализацию простогоWSGI server, обычно используемый для отладки сервера, рекомендуется использовать другиеWSGI server.
Реализация протокола WSGI
кDjangoНапример, проанализируемWSGIКонкретный процесс реализации протокола.
django WSGI application
WSGI applicationДолжен быть реализован как вызываемый объект, такой как функция, метод, класс (содержащий `call`метод). Нужно получить два параметра:
- Словарь, который может содержать информацию и другую информацию, запрошенную клиентом, может считаться контекстом запроса, обычно называемым
environment(В кодировании это часто сокращается какenviron,env) - Один для отправки статуса ответа HTTP (
HTTP status), заголовки ответов (HTTP headers) функция обратного вызова
Верните статус ответа и заголовки ответа через функцию обратного вызова вserverпри возврате тела ответ (response body), тело ответа повторяемо и содержит несколько строк. НижеDjangoсерединаapplicationКонкретная часть реализации:
class WSGIHandler(base.BaseHandler):
initLock = Lock()
request_class = WSGIRequest
def __call__(self, environ, start_response):
# 加载中间件
if self._request_middleware is None:
with self.initLock:
try:
# Check that middleware is still uninitialized.
if self._request_middleware is None:
self.load_middleware()
except:
# Unload whatever middleware we got
self._request_middleware = None
raise
set_script_prefix(get_script_name(environ))
# 请求处理之前发送信号
signals.request_started.send(sender=self.__class__, environ=environ)
try:
request = self.request_class(environ)
except UnicodeDecodeError:
logger.warning('Bad Request (UnicodeDecodeError)',
exc_info=sys.exc_info(),
extra={'status_code': 400,})
response = http.HttpResponseBadRequest()
else:
response = self.get_response(request)
response._handler_class = self.__class__
status = '%s %s' % (response.status_code, response.reason_phrase)
response_headers = [(str(k), str(v)) for k, v in response.items()]
for c in response.cookies.values():
response_headers.append((str('Set-Cookie'), str(c.output(header=''))))
# server提供的回调方法,将响应的header和status返回给server
start_response(force_str(status), response_headers)
if getattr(response, 'file_to_stream', None) is not None and environ.get('wsgi.file_wrapper'):
response = environ['wsgi.file_wrapper'](response.file_to_stream)
return response
Как можно заметитьapplicationПроцесс включает в себя:
- Загрузите все промежуточное программное обеспечение, выполните операции, связанные с Framework, установите префикс скрипта текущего потока и отправьте сигнал запуска запроса;
- обработать заявку, позвонить
get_response()Метод обрабатывает текущий запрос, и основная логика этого метода заключается в следующем:urlconfнайти соответствующийviewа такжеcallback, выполнять различныеmiddlewareа такжеcallback. - вызванный
serverвходящийstart_response()метод ответитheaderа такжеstatusВернуться кserver. - вернуть тело ответа
django WSGI Server
ответственный за получениеhttpзапрос, передать запросWSGI application,Зависит отapplicationвозврат после обработки запросаresponse. кDjangoвстроенныйserverВзгляните на конкретную реализацию в качестве примера.
пройти черезrunserverбегатьdjangoProject, вызовет в начале следующегоrunметод, создайтеWSGIServerэкземпляр , а затем вызовите егоserve_forever()способ запуска службы.
def run(addr, port, wsgi_handler, ipv6=False, threading=False):
server_address = (addr, port)
if threading:
httpd_cls = type(str('WSGIServer'), (socketserver.ThreadingMixIn, WSGIServer), {})
else:
httpd_cls = WSGIServer
# 这里的wsgi_handler就是WSGIApplication
httpd = httpd_cls(server_address, WSGIRequestHandler, ipv6=ipv6)
if threading:
httpd.daemon_threads = True
httpd.set_app(wsgi_handler)
httpd.serve_forever()
Следующее указываетWSGI serverКлючевые классы и методы в потоке обработки сервера.
- WSGIServer
run()Метод создаетWSGIServerПримеры, основная роль — получение клиентских запросов, передача запроса вapplication,Потомapplicationвернутьresponseвозвращен клиенту.- При создании экземпляра указывается
HTTPпросилhandler:WSGIRequestHandlerДобрый - пройти через
set_appа такжеget_appУстановить метод и получитьWSGIApplicationпримерwsgi_handler - При обработке http-запроса вызовите
handler_requestметод, создастWSGIRequestHandlerЭкземпляр обрабатывает http-запросы. -
WSGIServerсерединаget_requestметод переданsocketпринять данные запроса
- При создании экземпляра указывается
- WSGIRequestHandler
- Зависит от
WSGIServerвызовhandle_requestПри создании экземпляра передатьrequest,cient_address,WSGIServerтри параметра,__init__Когда метод создается, он также вызывает свой собственныйhandleметод -
handleметод создастServerHandlerэкземпляр, а затем вызвать егоrunспособ обработки запроса
- Зависит от
- ServerHandler
-
WSGIRequestHandlerВ своемhandleвызов методаrunметод, пройтиself.server.get_app()параметры, получитьWSGIApplication, а затем вызовите экземпляр (__call__),Получатьresponse, который пройдет вstart_responseобратный вызов, используемый для обработки возвращенногоheaderа такжеstatus. - пройти через
applicationПолучатьresponseпозже, черезfinish_responseвернутьresponse
-
- WSGIHandler
-
WSGIв соглашенииapplication, получает два параметра,environСловарь содержит информацию и другую информацию, запрошенную клиентом, ее можно считать контекстом запроса,start_responseдля отправки обратноstatusа такжеheaderфункция обратного вызова
-
Хотя тот, что вышеWSGI serverОн включает несколько реализаций классов и взаимные ссылки, но на самом деле принцип заключается в вызовеWSGIHandler, параметры входящего запроса и метод обратного вызоваstart_response()и вернуть ответ клиенту.
django simple_server
djangoизsimple_server.pyМодуль реализует простуюHTTPсервер и дает простойdemo, вы можете запустить его напрямую, и результат выполнения отобразит переменные среды, задействованные в запросе, в браузере.
который включает в себя всюhttpВсе компоненты запроса:
ServerHandler, WSGIServer, WSGIRequestHandler,так же какdemo_appупрощенный вариант представленияWSGIApplication.
Вы можете посмотреть на весь процесс:
if __name__ == '__main__':
# 通过make_server方法创建WSGIServer实例
# 传入建议application,demo_app
httpd = make_server('', 8000, demo_app)
sa = httpd.socket.getsockname()
print("Serving HTTP on", sa[0], "port", sa[1], "...")
import webbrowser
webbrowser.open('http://localhost:8000/xyz?abc')
# 调用WSGIServer的handle_request方法处理http请求
httpd.handle_request() # serve one request, then exit
httpd.server_close()
def make_server(
host, port, app, server_class=WSGIServer, handler_class=WSGIRequestHandler
):
"""Create a new WSGI server listening on `host` and `port` for `app`"""
server = server_class((host, port), handler_class)
server.set_app(app)
return server
# demo_app可调用对象,接受请求输出结果
def demo_app(environ,start_response):
from io import StringIO
stdout = StringIO()
print("Hello world!", file=stdout)
print(file=stdout)
h = sorted(environ.items())
for k,v in h:
print(k,'=',repr(v), file=stdout)
start_response("200 OK", [('Content-Type','text/plain; charset=utf-8')])
return [stdout.getvalue().encode("utf-8")]
demo_app()Представляет простую реализацию приложения WSGI черезmake_server()метод созданияWSGIServerэкземпляр, назовите егоhandle_request()метод, который вызываетdemo_app()Обработайте запрос и, наконец, верните ответ.
uWSGI
uWSGIОн направлен на разработку комплексного решения для развертывания сетевых приложений в распределенных кластерах. В основном дляwebи его стандартные услуги. Благодаря своей расширяемости его можно расширить для поддержки большего количества платформ и языков без ограничений.uWSGIЯвляетсяwebсервер, реализованныйWSGIпротокол,uwsgiпротокол,httpсоглашение и др.
uWSGIОсновные особенности:
- супер быстрая производительность
- Низкий объем памяти
- много
appуправлять - Функция подробного журнала (можно использовать для анализа
appпроизводительность и узкие места) - Широкие возможности настройки (ограничение объема памяти, перезапуск службы после определенного количества раз и т. д.)
uWSGIСервер реализует свои собственные на основеuwsgiпротоколserverраздел, нам просто нужноuwsgiуказывается в конфигурационном файлеapplicationадрес,uWSGIнепосредственно и фреймворк приложенияWSGI applicationкоммуникация.
эталонное чтение:
WSGI & uwsgi
WSGI Tutorial
Преимущества, недостатки и реализация интерфейса протокола wsgi для построения фреймворка mvc
Механизм связи Nginx и uWSGI
Понимание Python WSGI