django启动流程
调用栈
命令行输入以下命令时 python3 manage.py runserver
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()
概览
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()