Django請求生命周期分析

1.客戶端發送請求
- 在瀏覽器輸入url地址,例如
www.baidu.com,瀏覽器會自動補全協議(http),變為http://www.baidu.com,現在部分網站都實現了HSTS機制,服務器自動從http協議重定向到https協議 - 在網頁中點擊超鏈接或
javascript腳本進行url跳轉,僅設置href='絕對路徑',瀏覽器會自動使用當前url的協議、host和port,例如在https://tieba.baidu.com/index.html網頁中,點擊一個超鏈接/f?kw=chinajoy,會自動訪問https://tieba.baidu.com/f?kw=chinajoy
2. 路由轉發
- IP查找:因特網內每個公有IP都是唯一的,域名相當於IP的別名,因為我們無法去記住一大堆無意義的IP地址,但如果用一堆有意義的字母組成,大家就能快速訪問對應網站
- DNS解析:通過域名去查找IP,先從本地緩存查找,其中本地的
hosts文件也綁定了對應IP,若在本機中無法查到,那么就會去請求本地區域的域名服務器(通常是對應的網絡運營商如電信),這個通過網絡設置中的LDNS去查找,如果還是沒有找到的話,那么就去根域名服務器查找,這里有所有因特網上可訪問的域名和IP對應信息(根域名服務器全球共13台) - 路由轉發:通過網卡、路由器、交換機等設備,實現兩個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種情況處理請求:
- 如果是靜態資源(如javascript、css、圖片等)的請求,那么
nginx直接獲取到該資源,返回給用戶 - 如果是動態內容的請求,那么
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控制了從請求到響應的整個過程,首先的就是加載django的settings配置,然后就是調用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,例如獲取GET和POST參數,並且調用特定的模型對象執行數據庫操作,如果沒有數據庫操作,那么就直接跳到我們后續的14步了
12.models處理
視圖方法中,一般情況下都需要調用模型類進行數據操作,一般是通過模型的manager管理類進行操作的,如:MyModel.objects.get(pk=1)
如果沒有數據操作,那么這一步和下一步就忽略
13.數據庫操作
如果django通過模型類執行對數據庫的增刪改查,那么此時整個流程就會在對應的數據庫中執行
14.views處理數據
視圖方法獲取到數據后:
- 將數據封裝到一個
context字典當中,然后調用指定的template.html,通過模板中的變量、標簽和過濾器等,再結合傳入的數據context,會觸發中間件的process_template_response方法,最終渲染成HttpResponse - 不調用模板,直接返回數據,譬如
JsonResponse、FileResponse等 - 執行
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請求的生命周期結束。
