WSGI協議
Django是遵循WSGI協議設計的
WSGI協議主要包括server和application兩個部分:
- WSGI server:負責從客戶端接收請求,將request轉發給application,將application返回的response返回給客戶端
- WSGI application:接收由server轉發的request,處理請求,並將處理結果返回給server。application中可以包含多個棧式的中介軟體,這些中介軟體需要同時實現server與application:對server來說,中介軟體扮演應用程式;對應用程式來說,中介軟體扮演伺服器
可以選擇任意的server和application組合實現自己的web應用。
runserver後到底發生了什麼
通過runserver執行的Django主程式會建立一個WSGIServer的例項,WSGIServer父類是操作socket的TCPServer。
WSGIServer將開啟一個socket,並將此socket繫結到runserver引數中指定的ip和埠,然後呼叫socket.listen()開始監聽請求。
當請求來臨,WSGIServer會呼叫WSGIHandler這個application,在application中執行Django框架對請求資料的一系列處理。
runserver 0.0.0.0:8000
runserver 0.0.0.0:8000
表示將django程式使用的socket繫結ip設定為INADDR_ANY(0)
,因此socket會在8000埠監聽從本機所有網路卡發來的資料,相當於繫結了本機的所有ip地址。
比如你的機器有三個ip
192.168.1.1
202.202.202.202
61.1.2.3
使用runserver 0.0.0.0:8000
啟動的django程式可以通過伺服器的所有ip訪問到,而使用runserver 192.168.1.1:8000
,只有通過192.168.1.1:8000
才能夠訪問
如果本機有唯一的ip地址192.168.1.1
,那麼runserver 0.0.0.0:8000
就等同於 runserver 192.168.1.1:8000
runserver 127.0.0.1
表示將socket繫結到本機迴環地址,只能監聽本機對此服務的請求
runserver 0.0.0.0:0
如果不為socket指定繫結任何埠,或者將繫結的埠設定為0時,系統會在本機可選的埠中為socket隨機繫結一個
下面來實驗一下:
$ python manage.py runserver 0.0.0.0:0
Performing system checks...
System check identified no issues (0 silenced).
April 29, 2020 - 19:53:25
Django version 2.0.13, using settings 'qaboard.settings'
Starting development server at http://0.0.0.0:0/
Quit the server with CONTROL-C.
嘗試找到這個服務繫結的埠:
$ ps -ef|grep 0.0.0.0:0
luozx 896 19075 0 19:53 pts/28 00:00:00 python manage.py runserver 0.0.0.0:0
luozx 901 896 4 19:53 pts/28 00:00:04 /home/luozixi/myserver/venv/bin/python manage.py runserver 0.0.0.0:0
luozx 1070 28816 0 19:54 pts/37 00:00:00 grep 0.0.0.0:0
發現有兩個程式,這是因為runserver預設啟動兩個程式,一個程式是提供服務的django應用,一個程式用於檢測專案程式碼修改,如果有修改則自動重啟主程式
如果在runserver時使用 "--noreload" 引數則不會啟動檢測程式
$ python manage.py runserver 0.0.0.0:0 --noreload
$ ps -ef|grep 0.0.0.0:0
luozx 1429 19075 38 19:56 pts/28 00:00:01 python manage.py runserver 0.0.0.0:0 --noreload
luozx 1447 28816 0 19:56 pts/37 00:00:00 grep 0.0.0.0:0
檢視程式識別符號為1429的程式使用的socket繫結了哪個埠
$ netstat -nltp|grep 1429
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:48381 0.0.0.0:* LISTEN 1429/python
從伺服器的48381埠就可以訪問我們的django服務了
參考資料
Python Web開發最難懂的WSGI協議,到底包含哪些內容?
python從小白到入門:10分鐘搞懂WSGI協議
About IP 0.0.0.0 in Django
Socket.Bind(EndPoint) 方法
socket INADDR_ANY 監聽0.0.0.0地址 socket只繫結埠讓路由表決定傳到哪個ip