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請求的生命週期結束。