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