Чтобы заниматься веб-разработкой на Python, вам нужно понимать: WSGI и uwsgi.

Python uWSGI

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Фреймворк можно использовать в сочетании с реальной ситуацией проекта.

wsgi.png-22.9kB wsgi.png-22.9kB

картина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Ключевые классы и методы в потоке обработки сервера.

xiong (2).png-93.7kB xiong (2).png-93.7kB
  • 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