美文网首页
Flask源码剖析一之建立本地WSGIServer

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

作者: 羽煊 | 来源:发表于2019-06-16 00:54 被阅读0次

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

    相关文章

      网友评论

          本文标题:Flask源码剖析一之建立本地WSGIServer

          本文链接:https://www.haomeiwen.com/subject/hviifctx.html