美文网首页我爱编程
django源码分析之服务启动

django源码分析之服务启动

作者: 2hanson | 来源:发表于2018-04-15 23:00 被阅读0次

    服务运行

    Django项目有两种常见的运行方法,第一种主要用于测试开发环境,通过runserver命令启动,用Django自带的web server运行;另外一种主要用于正式生产环境,用gunicorn这样的WSGI server部署运行。

    runserver的运行方法

    第一种情况,一般通过命令python manage.py runserver启动,其中manage.py相关的代码具体在文章django源码分析之项目创建中已经详细描述,它的主要逻辑是根据用户输入来确定执行哪个命令。
    比如用户输入的服务启动命令python manage.py runserver,具体执行的命令就是runserver,代码位置在django/core/management/commands/runserver.py
    runserver中执行过程如下:

    handle() -> run() -> inner_run() -> django.core.servers.basehttp.run()
    

    其中django.core.servers.basehttp.run()django/core/servers/basehttp.py

    def run(addr, port, wsgi_handler, ipv6=False, threading=False, server_cls=WSGIServer):
        # 获取服务器地址
        server_address = (addr, port)
        if threading:
            httpd_cls = type('WSGIServer', (socketserver.ThreadingMixIn, server_cls), {})
        else:
            httpd_cls = server_cls
        # 创建一个socket server作为web服务器的作用,去监听端口
        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
        # 设置wsgi程序
        httpd.set_app(wsgi_handler)
        httpd.serve_forever()
    

    上面的wsgi_handler是一个wsgi程序,在runserver中传入

      def get_handler(self, *args, **options):
            """Return the default WSGI handler for the runner."""
            return get_internal_wsgi_application()
    

    其中django.core.servers.basehttp.get_internal_wsgi_application最后返回django.core.handlers.wsgi.WSGIHandler,在文件django/core/handlers/wsgi.py

    class WSGIHandler(base.BaseHandler):
        request_class = WSGIRequest
    
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.load_middleware()
    
        def __call__(self, environ, start_response):
            # 从environ中获取脚本目录前缀
            set_script_prefix(get_script_name(environ))
            # 启动request_started信号事件
            signals.request_started.send(sender=self.__class__, environ=environ)
            # 对environ进行进一步处理,使之成为在Django的view中的request参数
            request = self.request_class(environ)
            # 调用了BaseHandler中的self._get_response方法。
            response = self.get_response(request)
    
            response._handler_class = self.__class__
            # 返回response
            status = '%d %s' % (response.status_code, response.reason_phrase)
            response_headers = list(response.items())
            for c in response.cookies.values():
                response_headers.append(('Set-Cookie', c.output(header='')))
            start_response(status, response_headers)
            if getattr(response, 'file_to_stream', None) is not None and environ.get('wsgi.file_wrapper'):
                response = environ['wsgi.file_wrapper'](response.file_to_stream)
            return response
    

    通过WSGI server部署的运行方法

    WSGI是Web Server Gateway Interface的缩写。以层的角度来看,WSGI所在层的位置低于CGI。但与CGI不同的是WSGI具有很强的伸缩性且能运行于多线程或多进程的环境下,这是因为WSGI只是一份标准并没有定义如何去实现。实际上WSGI并非CGI,因为其位于web应用程序与web服务器之间,而web服务器可以是CGI,mod_python(注:现通常使用mod_wsgi代替),FastCGI或者是一个定义了WSGI标准的web服务器就像python标准库提供的独立WSGI服务器称为wsgiref。

    正常环境的部署方式,一遍通过WSGI server的配置文件直接指向项目的demo_project/wsgi.py文件

    """
    WSGI config for demo_project project.
    
    It exposes the WSGI callable as a module-level variable named ``application``.
    
    For more information on this file, see
    https://docs.djangoproject.com/en/2.0/howto/deployment/wsgi/
    """
    
    import os
    
    from django.core.wsgi import get_wsgi_application
    
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "demo_project.settings")
    
    application = get_wsgi_application()
    

    后续流程和runserver的基本一致

    相关文章

      网友评论

        本文标题:django源码分析之服务启动

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