django启动流程

调用栈

命令行输入以下命令时 python3 manage.py runserver

django启动流程

command

execute_from_command_line 函数中的 utility.execute() 会根据命令行的参数, 找到对应的 command 对象, 再去调用这个 command 对象的 run_from_argv 方法

服务模型

run 函数中会根据 threading 参数来选择服务模型, threading 默认为 True, 表示使用线程模型, 如果为 False 表示以传入的参数 server_cls 生成服务模型

# django\core\management\commands\runserver.py
def run(addr, port, wsgi_handler, ipv6=False, threading=True, server_cls=WSGIServer):
    server_address = (addr, port)
    if threading:
        httpd_cls = type('WSGIServer', (socketserver.ThreadingMixIn, server_cls), {})
    else:
        httpd_cls = server_cls
    httpd = httpd_cls(server_address, WSGIRequestHandler, ipv6=ipv6)
    if threading:
        # ThreadingMixIn.daemon_threads indicates how threads will behave on an
        # abrupt shutdown; like quitting the server by the user or restarting
        # by the auto-reloader. True means the server will not wait for thread
        # termination before it quits. This will make auto-reloader faster
        # and will prevent the need to kill the server manually if a thread
        # isn't terminating correctly.
        httpd.daemon_threads = True
    httpd.set_app(wsgi_handler)
    httpd.serve_forever()

handler

在 get_handler 步骤获取一个 handler, 之后把他传入 run 函数, 默认的 selector 接收到读写事件的时候会调用服务模型的 process_request 函数, 而这里默认的服务模型的 process_request 函数会产生一个新的线程, 执行 process_request_thread 函数, process_request_thread 函数会调用前面传入的 handler 来处理这个事件

这里默认情况下 线程模型 为 ThreadingMixIn, 他的 process_request 定义如下

# Lib\socketserver.py
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()

概览

django启动流程

def finish_request(self, request, client_address):
    """Finish one request by instantiating RequestHandlerClass."""
    self.RequestHandlerClass(request, client_address, self)

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)

RequestHandlerClass 是 django.core.servers.basehttp.WSGIRequestHandler 对象

request 是 selector 监听到的事件对象, client_address 是 selector 监听到的事件对应的发送方 ip 地址和 端口

根据 RequestHandlerClass 的 mro 追踪到最开始的 baseClass 我们发现 init 的定义如下

# mro:  (<class 'django.core.servers.basehttp.WSGIRequestHandler'>, <class 'wsgiref.simple_server.WSGIRequestHandler'>, <class 'http.server.BaseHTTPRequestHandler'>, <class 'socketserver.StreamRequestHandler'>, <class 'socketserver.Bas
eRequestHandler'>, <class 'object'>)
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()