django源碼分析之服務(wù)啟動(dòng)

服務(wù)運(yùn)行

Django項(xiàng)目有兩種常見的運(yùn)行方法,第一種主要用于測(cè)試開發(fā)環(huán)境,通過runserver命令啟動(dòng),用Django自帶的web server運(yùn)行;另外一種主要用于正式生產(chǎn)環(huán)境,用gunicorn這樣的WSGI server部署運(yùn)行。

runserver的運(yùn)行方法

第一種情況,一般通過命令python manage.py runserver啟動(dòng),其中manage.py相關(guān)的代碼具體在文章django源碼分析之項(xiàng)目創(chuàng)建中已經(jīng)詳細(xì)描述,它的主要邏輯是根據(jù)用戶輸入來確定執(zhí)行哪個(gè)命令。
比如用戶輸入的服務(wù)啟動(dòng)命令python manage.py runserver,具體執(zhí)行的命令就是runserver,代碼位置在django/core/management/commands/runserver.py。
runserver中執(zhí)行過程如下:

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):
    # 獲取服務(wù)器地址
    server_address = (addr, port)
    if threading:
        httpd_cls = type('WSGIServer', (socketserver.ThreadingMixIn, server_cls), {})
    else:
        httpd_cls = server_cls
    # 創(chuàng)建一個(gè)socket server作為web服務(wù)器的作用,去監(jiān)聽端口
    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
    # 設(shè)置wsgi程序
    httpd.set_app(wsgi_handler)
    httpd.serve_forever()

上面的wsgi_handler是一個(gè)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))
        # 啟動(dòng)request_started信號(hào)事件
        signals.request_started.send(sender=self.__class__, environ=environ)
        # 對(duì)environ進(jìn)行進(jìn)一步處理,使之成為在Django的view中的request參數(shù)
        request = self.request_class(environ)
        # 調(diào)用了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部署的運(yùn)行方法

WSGI是Web Server Gateway Interface的縮寫。以層的角度來看,WSGI所在層的位置低于CGI。但與CGI不同的是WSGI具有很強(qiáng)的伸縮性且能運(yùn)行于多線程或多進(jìn)程的環(huán)境下,這是因?yàn)閃SGI只是一份標(biāo)準(zhǔn)并沒有定義如何去實(shí)現(xiàn)。實(shí)際上WSGI并非CGI,因?yàn)槠湮挥趙eb應(yīng)用程序與web服務(wù)器之間,而web服務(wù)器可以是CGI,mod_python(注:現(xiàn)通常使用mod_wsgi代替),F(xiàn)astCGI或者是一個(gè)定義了WSGI標(biāo)準(zhǔn)的web服務(wù)器就像python標(biāo)準(zhǔn)庫(kù)提供的獨(dú)立WSGI服務(wù)器稱為wsgiref。

正常環(huán)境的部署方式,一遍通過WSGI server的配置文件直接指向項(xiàng)目的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()

后續(xù)流程和runserver的基本一致

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容