flask 程序運行起來后就在本地建立起了wsgi server ,監(jiān)聽了本地的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對象。并執(zhí)行了該對象的serve_forever()來建立起本地wsgi server的肌毅。
繼續(xù)分析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 會根據(jù)app.run()時提供的參數(shù)決定采用什么方式工作默認是線程模式筷转。
app.run()中提供的參數(shù)是processes=n 時,1<n<40,用多進程方式工作芽腾。多進程方式時旦装,make_server會返回一個ForkingWSGIServer對象。
app.run()中提供的參數(shù)是threaded=True時摊滔,用多線程方式工作阴绢。這時make_server會返回一個ThreadedWSGIServer對象。
不管用哪種方式工作艰躺,都會實現(xiàn)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。
繼續(xù)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在后面會被觸發(fā)左电。
繼續(xù)父類HTTPServer的分析HTTPServer(socketserver.TCPServer)。
HTTPServer其實啥也沒做页响,只是繼承了socketserver.TCPServer篓足。繼續(xù)對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類中實現(xiàn)了serve.forever方法栈拖,并最終對self.RequestHandlerClass 即WSGIRequestHandler進行了實例化。BaseServer類的process_request方法在ForkingMixIn和 ThreadingMixIn中進程了重寫没陡。在多進程和多線程模式下會調(diào)用各自的process_request涩哟。
ForkingMixIn和ThreadingMixIn分別是ForkingWSGIServer和ThreadedWSGIServer的父類,F(xiàn)orkingWSGIServer和ThreadedWSGIServer是實現(xiàn)多進程和多線程的重要類盼玄。
現(xiàn)在再回頭去看看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()
多線程方式會調(diào)用ThreadingMixIn.process_request,在該方法中創(chuàng)建線程,self.process_request_thread又調(diào)用了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。
現(xiàn)在分析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 的實例化最終是執(zhí)行了BaseRequestHandler的__init__
并觸發(fā)了handle()方法的執(zhí)行暴心。
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執(zhí)行流程為 handler()-> BaseHTTPRequestHandler.handler() -> WSGIRequestHandler.handle_one_request() .在handle_one_request()中最終執(zhí)行了run_wsgi().run_wsgi()中的def execute(app)會最終觸發(fā)self.app()的執(zhí)行execute(self.server.app)杂拨。
self.app 就是Flask對象。這個app()的執(zhí)行悯衬,也即為Flask 類里面的__call__
方法的執(zhí)行弹沽。隨后將進入上下文處理階段。
見Flask源碼剖析二