Flask源码剖析一之建立本地WSGIServer

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 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源码剖析二

你可能感兴趣的:(Flask源码剖析一之建立本地WSGIServer)