Python Web开发中的WSGI协议简介(4)

在响应时间较短的应用中,uWSGI+django是个不错的组合(测试的结果来看有稍微那么一点优势),但是如果有部分阻塞请求 Gunicorn+gevent+django有非常好的效率, 如果阻塞请求比较多的话,还是用tornado重写吧。

Middleware

WSGI除了server和application两个角色外,还有middleware中间件,middleware运行在server和application中间,同时具备server和application的角色,对于server来说,它是一个application,对于application来说,它是一个server:

from piglatin import piglatin

 

class LatinIter:

 

    def __init__(self, result, transform_ok):

        if hasattr(result, 'close'):

            self.close = result.close

        self._next = iter(result).__next__

        self.transform_ok = transform_ok

 

    def __iter__(self):

        return self

 

    def __next__(self):

        if self.transform_ok:

            return piglatin(self._next())  # call must be byte-safe on Py3

        else:

            return self._next()

 

class Latinator:

 

    # by default, don't transform output

    transform = False

 

    def __init__(self, application):

        self.application = application

 

    def __call__(self, environ, start_response):

 

        transform_ok = []

 

        def start_latin(status, response_headers, exc_info=None):

 

            # Reset ok flag, in case this is a repeat call

            del transform_ok[:]

 

            for name, value in response_headers:

                if name.lower() == 'content-type' and value == 'text/plain':

                    transform_ok.append(True)

                    # Strip content-length if present, else it'll be wrong

                    response_headers = [(name, value)

                        for name, value in response_headers

                            if name.lower() != 'content-length'

                    ]

                    break

 

            write = start_response(status, response_headers, exc_info)

 

            if transform_ok:

                def write_latin(data):

                    write(piglatin(data))  # call must be byte-safe on Py3

                return write_latin

            else:

                return write

 

        return LatinIter(self.application(environ, start_latin), transform_ok)

 

 

from foo_app import foo_app

run_with_cgi(Latinator(foo_app))

可以看出,Latinator调用foo_app充当server角色,然后实例被run_with_cgi调用充当application角色。

uWSGI、uwsgi与WSGI的区别

- uwsgi:与WSGI一样是一种通信协议,是uWSGI服务器的独占协议,据说该协议是fastcgi协议的10倍快。

- uWSGI:是一个web server,实现了WSGI协议、uwsgi协议、http协议等。

Django中WSGI的实现

每个Django项目中都有个wsgi.py文件,作为application是这样实现的:

from django.core.wsgi import get_wsgi_application

application = get_wsgi_application()

源码:

from django.core.handlers.wsgi import WSGIHandler

 

def get_wsgi_application():

 

    django.setup(set_prefix=False)

    return WSGIHandler()

WSGIHandler:

class WSGIHandler(base.BaseHandler):

    request_class = WSGIRequest

 

    def __init__(self, *args, **kwargs):

        super().__init__(*args, **kwargs)

        self.load_middleware()

 

    def __call__(self, environ, start_response):

        set_script_prefix(get_script_name(environ))

        signals.request_started.send(sender=self.__class__, environ=environ)

        request = self.request_class(environ)

        response = self.get_response(request)

 

        response._handler_class = self.__class__

 

        status = '%d %s' % (response.status_code, response.reason_phrase)

        response_headers = [

            *response.items(),

            *(('Set-Cookie', c.output(header='')) for c in response.cookies.values()),

        ]

        start_response(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

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/5a18f0a52638df07849bb2b45c5090b7.html