flask 程序运行起来后就在本地建立起了wsgi server ,监听了本地的5000端口,本文从app.run()开始追踪wsgiserver 建立的过程。
flask.app.Flask.run
这个方法中最重要的一句是run_simple(host, port, self, **options),注意该方法传入self,其实就是app方法。
werkzeug.serving.run_simple
def inner():
try:
fd = int(os.environ["WERKZEUG_SERVER_FD"])
except (LookupError, ValueError):
fd = None
srv = make_server(
hostname,
port,
application,
threaded,
processes,
request_handler,
passthrough_errors,
ssl_context,
fd=fd,
)
if fd is None:
log_startup(srv.socket)
srv.serve_forever()
在run_simple方法中有个inner方法,该方法实例化了make_server对象。并执行了该对象的serve_forever()来建立起本地wsgi server的。
继续分析make_server 对象
def make_server(
host=None,
port=None,
app=None,
threaded=False,
processes=1,
request_handler=None,
passthrough_errors=False,
ssl_context=None,
fd=None,
):
if threaded and processes > 1:
raise ValueError("cannot have a multithreaded and multi process server.")
elif threaded:
#线程
return ThreadedWSGIServer(
host, port, app, request_handler, passthrough_errors, ssl_context, fd=fd
)
elif processes > 1:
#多进程
return ForkingWSGIServer(
host,
port,
app,
processes,
request_handler,
passthrough_errors,
ssl_context,
fd=fd,
)
else:
#IO多路复用
return BaseWSGIServer(
host, port, app, request_handler, passthrough_errors, ssl_context, fd=fd
)
make_server 会根据app.run()时提供的参数决定采用什么方式工作默认是线程模式。
app.run()中提供的参数是processes=n 时,1<n<40,用多进程方式工作。多进程方式时,make_server会返回一个ForkingWSGIServer对象。
app.run()中提供的参数是threaded=True时,用多线程方式工作。这时make_server会返回一个ThreadedWSGIServer对象。
不管用哪种方式工作,都会实现BaseWSGIServer 对象。
class ForkingWSGIServer(ForkingMixIn, BaseWSGIServer):
"""A WSGI server that does forking."""
multiprocess = True
def __init__(
self,
host,
port,
app,
processes=40,
handler=None,
passthrough_errors=False,
ssl_context=None,
fd=None,
):
if not can_fork:
raise ValueError("Your platform does not support forking.")
BaseWSGIServer.__init__(
self, host, port, app, handler, passthrough_errors, ssl_context, fd
)
self.max_children = processes
class ThreadedWSGIServer(ThreadingMixIn, BaseWSGIServer):
"""A WSGI server that does threading."""
multithread = True
daemon_threads = True
从上面的代码中可以看出不管是多进程的ForkingWSGIServer还是多线程的 ThreadedWSGIServer 都继承了BaseWSGIServer。
继续BaseWSGIServer的分析
werkzeug.serving.BaseWSGIServer
class BaseWSGIServer(HTTPServer, object):
def __init__(
self,
host,
port,
app,
handler=None,
passthrough_errors=False,
ssl_context=None,
fd=None,
):
if handler is None:
handler = WSGIRequestHandler
HTTPServer.__init__(self, server_address, handler)
def serve_forever(self):
self.shutdown_signal = False
try:
HTTPServer.serve_forever(self)
except KeyboardInterrupt:
pass
finally:
self.server_close()
这段代码中将WSGIRequestHandler注册到了BaseWSGIServer,WSGIRequestHandler在后面会被触发。
继续父类HTTPServer的分析HTTPServer(socketserver.TCPServer)。
HTTPServer其实啥也没做,只是继承了socketserver.TCPServer。继续对TCPServer进行分析。
socketserver
class TCPServer(BaseServer):
def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True):
"""Constructor. May be extended, do not override."""
BaseServer.__init__(self, server_address, RequestHandlerClass)
self.socket = socket.socket(self.address_family,
self.socket_type)
if bind_and_activate:
try:
self.server_bind()
self.server_activate()
except:
self.server_close()
raise
TCPServer类扩展了BaseServer并将WSGIRequestHandler传给了BaseServer。
socketserver
class BaseServer:
def serve_forever(self, poll_interval=0.5):
self._handle_request_noblock()
def _handle_request_noblock(self):
self.process_request(request, client_address)
def process_request(self, request, client_address):
"""Call finish_request.
Overridden by ForkingMixIn and ThreadingMixIn.
"""
self.finish_request(request, client_address)
def finish_request(self, request, client_address):
self.RequestHandlerClass(request, client_address, self)
BaseServer类中实现了serve.forever方法,并最终对self.RequestHandlerClass 即WSGIRequestHandler进行了实例化。BaseServer类的process_request方法在ForkingMixIn和 ThreadingMixIn中进程了重写。在多进程和多线程模式下会调用各自的process_request。
ForkingMixIn和ThreadingMixIn分别是ForkingWSGIServer和ThreadedWSGIServer的父类,ForkingWSGIServer和ThreadedWSGIServer是实现多进程和多线程的重要类。
现在再回头去看看ForkingMixIn和 ThreadingMixIn中的process_request 。
socketserver.ForkingMixIn
多进程处理类
class ForkingMixIn:
def process_request(self, request, client_address):
"""Fork a new subprocess to process the request."""
pid = os.fork()
if pid:
# Parent process
if self.active_children is None:
self.active_children = set()
self.active_children.add(pid)
self.close_request(request)
return
else:
# Child process.
# This must never return, hence os._exit()!
status = 1
try:
self.finish_request(request, client_address)
status = 0
except Exception:
self.handle_error(request, client_address)
finally:
try:
self.shutdown_request(request)
finally:
os._exit(status)
多线程处理类
class ThreadingMixIn:
def process_request_thread(self, request, client_address):
"""Same as in BaseServer but as a thread.
In addition, exception handling is done here.
"""
try:
self.finish_request(request, client_address)
except Exception:
self.handle_error(request, client_address)
finally:
self.shutdown_request(request)
def process_request(self, request, client_address):
"""Start a new thread to process the request."""
t = threading.Thread(target = self.process_request_thread,
args = (request, client_address))
t.daemon = self.daemon_threads
if not t.daemon and self.block_on_close:
if self._threads is None:
self._threads = []
self._threads.append(t)
t.start()
多线程方式会调用ThreadingMixIn.process_request,在该方法中创建线程,self.process_request_thread又调用了self.finish_request(request, client_address),回到BaseServer中的finish_request
def finish_request(self, request, client_address):
self.RequestHandlerClass(request, client_address, self)
self.RequestHandlerClass(),也就是实例化WSGIRequestHandler。
现在分析WSGIRequestHandler,WSGIRequestHandler是一个多继承类
werkzeug.serving
class WSGIRequestHandler(BaseHTTPRequestHandler, object)
http.server
class BaseHTTPRequestHandler(socketserver.StreamRequestHandler)
socketserver
class StreamRequestHandler(BaseRequestHandler)
socketserver
class BaseRequestHandler:
def __init__(self, request, client_address, server):
self.request = request
self.client_address = client_address
self.server = server
self.setup()
try:
self.handle()
finally:
self.finish()
def setup(self):
pass
def handle(self):
pass
def finish(self):
pass
由此可见,对WSGIRequestHandler 的实例化最终是执行了BaseRequestHandler的__init__
并触发了handle()方法的执行。
WSGIRequestHandler对handle方法进行了重写。
class WSGIRequestHandler(BaseHTTPRequestHandler, object):
def run_wsgi(self):
def execute(app):
application_iter = app(environ, start_response)
try:
execute(self.server.app)
def handle(self):
"""Handles a request ignoring dropped connections."""
rv = None
try:
rv = BaseHTTPRequestHandler.handle(self)
def handle_one_request(self):
"""Handle a single HTTP request."""
self.raw_requestline = self.rfile.readline()
if not self.raw_requestline:
self.close_connection = 1
elif self.parse_request():
return self.run_wsgi()
class BaseHTTPRequestHandler(socketserver.StreamRequestHandler):
def handle(self):
"""Handle multiple requests if necessary."""
self.close_connection = True
self.handle_one_request()
while not self.close_connection:
self.handle_one_request()
WSGIRequestHandler的handle执行流程为 handler()-> BaseHTTPRequestHandler.handler() -> WSGIRequestHandler.handle_one_request() .在handle_one_request()中最终执行了run_wsgi().run_wsgi()中的def execute(app)会最终触发self.app()的执行execute(self.server.app)。
self.app 就是Flask对象。这个app()的执行,也即为Flask 类里面的__call__
方法的执行。随后将进入上下文处理阶段。
见Flask源码剖析二
网友评论