Django(35)Django請求生命週期分析(超詳細)

Silent丿丶黑羽發表於2021-05-27

Django請求生命週期分析


 

1.客戶端傳送請求

  1. 在瀏覽器輸入url地址,例如www.baidu.com,瀏覽器會自動補全協議(http),變為http://www.baidu.com,現在部分網站都實現了HSTS機制,伺服器自動從http協議重定向到https協議
  2. 在網頁中點選超連結或javascript指令碼進行url跳轉,僅設定href='絕對路徑',瀏覽器會自動使用當前url的協議、host和port,例如在https://tieba.baidu.com/index.html網頁中,點選一個超連結/f?kw=chinajoy,會自動訪問https://tieba.baidu.com/f?kw=chinajoy
     

2. 路由轉發

  1. IP查詢:因特網內每個公有IP都是唯一的,域名相當於IP的別名,因為我們無法去記住一大堆無意義的IP地址,但如果用一堆有意義的字母組成,大家就能快速訪問對應網站
  2. DNS解析:通過域名去查詢IP,先從本地快取查詢,其中本地的hosts檔案也繫結了對應IP,若在本機中無法查到,那麼就會去請求本地區域的域名伺服器(通常是對應的網路運營商如電信),這個通過網路設定中的LDNS去查詢,如果還是沒有找到的話,那麼就去根域名伺服器查詢,這裡有所有因特網上可訪問的域名和IP對應資訊(根域名伺服器全球共13臺)
  3. 路由轉發:通過網路卡、路由器、交換機等裝置,實現兩個IP地址之間的通訊。用到的主要就是路由轉發技術,根據路由表去轉發報文,還有子網掩碼、IP廣播等等知識點
     

3.建立連線

通過TCP協議的三次握手建立連線
 

4.傳輸報文

建立連線後,客戶端會通過TCP依次、有序的傳送一定大小的報文,其中包括了超時重傳、阻塞視窗等等概念,用來保證資料包的完整、有序

  • http協議使用的明文傳輸,所有內容都是直接可讀的
  • https協議是基於SSL/TLS加密,而SSL/TLS是基於TCP協議的,也就是http協議報文包裝成TCP報文進行的加密,使用https協議的話,如果本地沒有證照和公鑰,那麼會從伺服器獲取證照並且進行驗證,流程如下:

     

5.nginx處理

當前django框架開發的web專案,主流使用的伺服器架構是:nginx+uWSGI+django
nginx監聽公網IP的某個埠,例如80,接收到請求後,分2種情況處理請求:

  1. 如果是靜態資源(如javascript、css、圖片等)的請求,那麼nginx直接獲取到該資源,返回給使用者
  2. 如果是動態內容的請求,那麼nginx就將請求轉發到uWSGI,使用的協議一般都是uwsgi,效能最好

注意:

  • 有些reqeust會分多個資料包進行傳送,nginx會快取等待整個request接收完成才呼叫uWSGI
  • 如果使用的https,那麼加密、解密都在nginx中進行處理

 

6.uWSGI處理

uWSGI監聽本機IP的某個埠,例如3308,接收到nginx轉發來的請求後,通過將http協議轉換為WSGI協議,和django程式之間進行通訊
 

7.WSGIHandler處理

當django接受到一個請求時,會初始化一個WSGIHandler,可以在專案下的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):
        set_script_prefix(get_script_name(environ))
        signals.request_started.send(sender=self.__class__, environ=environ)
        request = self.request_class(environ)
        response = self.get_response(request)
        
    ......

它接受2個引數:

  • environ:是含有伺服器端的環境變數
  • start_response:可呼叫物件,返回一個可迭代物件。

這個handler控制了從請求到響應的整個過程,首先的就是載入djangosettings配置,然後就是呼叫django的中介軟體開始操作
 

8.middleware中介軟體處理

django操作中介軟體,首先會呼叫process_request方法,該方法的作用是處理請求物件,它的引數是request,返回有2種情況

  • response:呼叫process_response列表處理
  • None:呼叫下一個中介軟體的process_request處理

返回response之後的中介軟體及其業務邏輯都不會處理,直接回返回給瀏覽器
返回None則表示會繼續呼叫下一個中介軟體,處理下一個中介軟體中的邏輯
 
django專案預設有一些自帶的中介軟體,如下:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

process_request會從上往下依次呼叫MIDDLEWARE中的中介軟體,注意:中介軟體的執行是有順序的,所以我們一般自定義中介軟體的時候,我們都會將自定義的中介軟體放到列表最下面

 

9.URLConf路由匹配

通過urls.py檔案中的 urlpatterns 配置找到對應的 檢視函式或者檢視類的方法,如果沒有找到匹配的方法,那麼就會觸發異常,由中介軟體的process_exception 進行處理
process_exception:在檢視函式或中介軟體處理過程丟擲異常時呼叫
引數:

  • request:請求物件
  • exception:是處理過程中丟擲的異常物件

返回:

  • response:之後的process_exception都不會觸發,而是呼叫process_response處理
  • None:呼叫上一個中介軟體的process_exception處理

 

10.middleware的process_view

我們通過路由呼叫檢視之前,會呼叫中介軟體的process_view方法進行預處理
process_view:檢視預處理,在檢視函式處理之前呼叫
引數:

  • view_func:url路由匹配到的檢視函式
  • view_args:檢視函式的可變引數
  • view_kwargs:檢視函式的可變關鍵字引數

返回:

  • response:呼叫process_response處理
  • None:呼叫下一個中介軟體的process_view處理

 

11.views處理request

呼叫對應的檢視函式或檢視類的方法處理request,例如獲取GETPOST引數,並且呼叫特定的模型物件執行資料庫操作,如果沒有資料庫操作,那麼就直接跳到我們後續的14步了
 

12.models處理

檢視方法中,一般情況下都需要呼叫模型類進行資料操作,一般是通過模型的manager管理類進行操作的,如:MyModel.objects.get(pk=1)
如果沒有資料操作,那麼這一步和下一步就忽略
 

13.資料庫操作

如果django通過模型類執行對資料庫的增刪改查,那麼此時整個流程就會在對應的資料庫中執行
 

14.views處理資料

​檢視方法獲取到資料後:

  • 將資料封裝到一個context字典當中,然後呼叫指定的template.html,通過模板中的變數、標籤和過濾器等,再結合傳入的資料context,會觸發中介軟體的process_template_response方法,最終渲染成HttpResponse
  • 不呼叫模板,直接返回資料,譬如 JsonResponseFileResponse
  • 執行redirect,生成一個重定向的HttpResponse,觸發中介軟體的process_response後,返回到客戶端,結束該web請求的生命週期
     

15.middleware的process_response

呼叫中介軟體的 process_response 方法進行處理,最後一箇中介軟體的process_response執行完成後,返回到WSGIHandler類中
 

16.WSGIHandler處理

WSGIHandler類獲取到response後

  • 先處理response的響應行和響應頭,然後呼叫 start_response 返回http協議的 響應行和響應頭 到uWSGI,這個 start_response 只能呼叫一次
  • 第一步處理完成後,如果是檔案需要對response進行,否則就直接將response作為http協議的body部分返回給uWSGI
     

17.uWSGI處理

uWSGI接收到django程式的返回後,將所有內容包裝成http協議的內容後,通過uwsgi協議返回給nginx伺服器處理
 

18.nginx處理

nginx獲取到uWSGI的返回後,將response通過TCP協議返回給客戶端
 

19.客戶端接收響應

客戶端接收到伺服器的響應後,做對應的操作,例如:顯示在瀏覽器中,或是javascript的處理等至此,整個web請求的生命週期結束。

相關文章