WSGI 協議
WSGI:是一種協議規范,起到規范參數的作用,就像告訴公路一樣,規定超車靠右行,速度不低於90km/h,等。但這一切都是對雙方進行溝通,比如,重慶到武漢這條高速路,這兒重慶和武漢就各為一端,他們之間的行車規范就按照WSGI規則即可。我們現在需要記住,WSGI溝通的雙方是wsgi server (比如uWSGI) 要和 wsgi application(比如django )
wsgi server (比如uWSGI)實現wsgi協議規范的服務器我們叫做wsgi服務器,也就是uWSGI服務器,
wsgi application(比如django )實現wsgi協議的應用,我們叫做wsgi應用,比如Django,Falsk
uWSGI
uWGSI:是一個web服務器,或者wsgi server服務器,他的任務就是接受用戶請求,由於用戶請求是通過網絡發過來的,其中用戶到服務器端之間用的是http協議,所以我們uWSGI要想接受並且正確解出相關信息,我們就需要uWSGI實現http協議,沒錯,uWSGI里面就實現了http協議。所以現在我們uWSGI能准確接受到用戶請求,並且讀出信息。現在我們的uWSGI服務器需要把信息發給Django,我們就需要用到WSGI協議,剛好uWSGI實現了WSGI協議,所以。uWSGI把接收到的信息作一次簡單封裝傳遞給Django,Django接收到信息后,再經過一層層的中間件,於是,對信息作進一步處理,最后匹配url,傳遞給相應的視圖函數,視圖函數做邏輯處理......后面的就不敘述了,然后將處理后的數據通過中間件一層層返回,到達Djagno最外層,然后,通過WSGI協議將返回數據返回給uWSGI服務器,uWSGI服務器通過http協議將數據傳遞給用戶。這就是整個流程。
這個過程中我們似乎沒有用到uwsgi協議,但是他也是uWSGI實現的一種協議,魯迅說過,存在即合理,所以說,他肯定在某個地方用到了。我們過一會再來討論
我們可以用這條命令:python manage.py runserver,啟動Django自帶的服務器,具體叫什么名字,我真不知道(知道的可以留言)。DJango自帶的服務器(runserver 起來的 HTTPServer 就是 Python 自帶的 simple_server)。是默認是單進程單多線程的,對於同一個http請求,總是先執行一個,其他等待,一個一個串行執行。無法並行。而且django自帶的web服務器性能也不好,只能在開發過程中使用。於是我們就用uWSGI代替了。但是uWSGI也不夠好,為什么看下圖。
為什么有了uWSGI為什么還需要nginx?
因為nginx具備優秀的靜態內容處理能力,然后將動態內容轉發給uWSGI服務器,這樣可以達到很好的客戶端響應。支持的並發量更高,方便管理多進程,發揮多核的優勢,提升性能。這時候nginx和uWSGI之間的溝通就要用到uwsgi協議。
雜談
django 的並發能力真的是令人擔憂,這里就使用 nginx + uwsgi 提供高並發
nginx 的並發能力超高,單台並發能力過萬(這個也不是絕對),在純靜態的 web 服務中更是突出其優越的地方,由於其底層使用 epoll 異步IO模型進行處理,使其深受歡迎
做過運維的應該都知道,
Python需要使用nginx + uWSGI 提供靜態頁面訪問,和高並發
php 需要使用 nginx + fastcgi 提供高並發,
java 需要使用 nginx + tomcat 提供 web 服務
django 原生為單線程序,當第一個請求沒有完成時,第二個請求輝阻塞,知道第一個請求完成,第二個請求才會執行。 Django就沒有用異步,通過線程來實現並發,這也是WSGI普遍的做法,跟tornado不是一個概念 官方文檔解釋django自帶的server默認是多線程 django開兩個接口,第一個接口sleep(20),另一個接口不做延時處理(大概耗時幾毫秒) 先請求第一個接口,緊接着請求第二個接口,第二個接口返回數據,第一個接口20秒之后返回數據 證明django的server是默認多線程 啟動uWSGI服務器 # 在django項目目錄下 Demo工程名 uwsgi --http 0.0.0.0:8000 --file Demo/wsgi.py
經過上述的步驟測試,發現在這種情況下啟動django項目,uWSGI也是單線程,訪問接口需要"排隊" 不給uWSGI加進程,uWSGI默認是單進程單線程 uwsgi --http 0.0.0.0:8000 --file Demo/wsgi.py --processes 4 --threads 2 # processes: 進程數 # processes 和 workers 一樣的效果 # threads : 每個進程開的線程數
經過測試,接口可以"同時"訪問,uWSGI提供多線程
- Python因為GIL的存在,在一個進程中,只允許一個線程工作,導致單進程多線程無法利用多核
- 多進程的線程之間不存在搶GIL的情況,每個進程有一個自己的線程鎖,多進程多GIL