1. 程式人生 > 其它 >Django+Nginx+Uwsgi(全網最全步驟工作原理流程與部署歷程)

Django+Nginx+Uwsgi(全網最全步驟工作原理流程與部署歷程)

一、必要前提

1.1 準備知識

  • django
一個基於python的開源web框架,請確保自己熟悉它的框架目錄結構。
  • uWSGI
一個基於自有的uwsgi協議、wsgi協議和http服務協議的web閘道器
  • nginx
常用高效能代理伺服器
  • wsgi.py
1 django專案攜帶的一個wsgi介面檔案
2 如果專案名叫destiny的話,此檔案就位於[destiny/destiny/wsgi.py]

1.2 相關資料

wsgi:一種實現python解析的通用介面標準/協議,是一種通用的介面標準或者介面協議,實現了python web程式與伺服器之間互動的通用性。 
利用它,web.py或bottle或者django等等的python web開發框架,就可以輕鬆地部署在不同的web server上了;

uwsgi:同WSGI一樣是一種通訊協議 
uwsgi協議是一個uWSGI伺服器自有的協議,它用於定義傳輸資訊的型別,它與WSGI相比是兩樣東西。

uWSGI :一種python web server或稱為Server/Gateway 
uWSGI類似tornadoweb或者flup,是一種python web server,uWSGI是實現了uwsgi和WSGI兩種協議的Web伺服器,負責響應python 的web請求。 
因為apache、nginx等,它們自己都沒有解析動態語言如php的功能,而是分派給其他模組來做,比如apache就可以說內建了php模組,讓人感覺好像apache就支援php一樣。 
uWSGI實現了wsgi協議、uwsgi協議、http等協議。 Nginx中HttpUwsgiModule的作用是與uWSGI伺服器進行交換。

  

1.3 專案流程
其實網上很多教程,都是關於uwsgi+nginx部署django的,StackOverflow也有一些解決常見錯誤的方法,但是部署還是容易出問題,新手難解決。
歸根到底是自己不瞭解整個專案的流程。教程都只教方法,但為什麼這樣部署,這樣部署有什麼好處,每個元件都起什麼作用卻隻字不提。致使只要部署稍微有那麼一點不同,就無可是從了。
所以說,專案流程和每個元件的用途才是此次部署最重要的部分。

1 首先客戶端請求服務資源,
2 nginx作為直接對外的服務介面,接收到客戶端傳送過來的http請求,會解包、分析,
3 如果是靜態檔案請求就根據nginx配置的靜態檔案目錄,返回請求的資源,
4 如果是動態的請求,nginx就通過配置檔案,將請求傳遞給uWSGI;uWSGI 將接收到的包進行處理,並轉發給wsgi, 5 wsgi根據請求呼叫django工程的某個檔案或函式,處理完後django將返回值交給wsgi, 6 wsgi將返回值進行打包,轉發給uWSGI, 7 uWSGI接收後轉發給nginx,nginx最終將返回值返回給客戶端(如瀏覽器)。 8 *注:不同的元件之間傳遞資訊涉及到資料格式和協議的轉換

作用:
1. 第一級的nginx並不是必須的,uwsgi完全可以完成整個的和瀏覽器互動的流程;
2. 在nginx上加上安全性或其他的限制,可以達到保護程式的作用;
3. uWSGI本身是內網介面,開啟多個work和processes可能也不夠用,而nginx可以代理多臺uWSGI完成uWSGI的負載均衡;


4. django在debug=False下對靜態檔案的處理能力不是很好,而用nginx來處理更加高效。

二、安裝與配置
首先確保你已經安裝好了nginx並可以正常使用
其次確保自己安裝完成了python,並已經完成了pip的安裝。如果沒有,請先安裝。
接著別忘了確認自己專案所需的django已經完成安裝正常工作
沒有的話參考以下命令安裝django , 建立一個工程或利用已經寫好的工程,開啟瀏覽器,輸入部署地址(如:http://127.0.0.1:8000/)(或http://內網ip:8000、或http://外網ip:8000)測試,確認是否可正常開啟瀏覽。

1 安裝:sudo pip install django==1.10
2 測試:python manage.py runserver 0.0.0.0:8000

上面的工作都完成了,接著安裝uWSGI

1 sudo pip install uwsgi

測試uWSGI: 新建檔案test.py,寫入以下內容

1 def application(env, start_response):
2     start_response('200 OK', [('Content-Type','text/html')])
3     return "Hello World"

執行

1 sudo uwsgi --http 0.0.0.0:8000 --wsgi-file test.py

如果端口占用,使用

1 lsof -i :8000

列出佔用埠的程式的pid號,並使用以下命令殺掉所有佔用埠的程式

1 sudo kill -9 pid

然後瀏覽http://127.0.0.1:8000(或http://內網ip:8000、或http://外網ip:8000)檢視效果,有”Hello World”輸出即安裝成功。

下一步建立工程單獨的nginx配置檔案
首先確認自己準確的知道nginx的預設配置檔案目錄(nginx.conf)的路徑,如果不清楚,請使用如下命令獲取:

1 nginx -t

大概會列出以下類似資訊:

1 nginx: the configuration file /etc/nginx/conf/nginx.conf syntax is ok
2 nginx: configuration file /etc/nginx/conf/nginx.conf test is successful

裡面說明了nginx預設配置檔案的路徑是:/etc/nginx/conf/nginx.conf;

然後,確保nginx.conf的同目錄下有uwsgi_params檔案(/etc/nginx/conf/uwsgi_params),沒有的話根據連結獲取, 後面要用到。

在自己的工程目錄下建立如destiny.conf(/wwwroot/destiny/destiny.conf)的配置檔案;複製nginx.conf裡面全部的內容,全部寫入destiny.conf中。
然後按照下面寫的,把destiny.conf配置檔案中的server段部分全部替換掉。

 1 server {
 2     listen 80;
 3     server_name localhost;
 4     charset     utf-8;
 5     access_log      /wwwroot/destiny/nginx_access.log;
 6     error_log       /wwwroot/destiny/nginx_error.log;
 7     client_max_body_size 75M;
 8 
 9 
10     location /static {
11         alias /wwwroot/destiny/destiny/static;
12     }
13 
14     location / {
15         include     /etc/nginx/conf/uwsgi_params;
16         uwsgi_pass  127.0.0.1:9090;
17     }
18 }

其中的 listen 80代表伺服器開放80埠;
location [目錄名]代表專案路徑的引導;
access_log 和error_log是定義nginx訪問日誌和錯誤日誌的存放路徑。
“location /static”中的”/static”是自己定義的專案引用靜態檔案時,瀏覽器中顯示的靜態資源所在的根目錄名;這樣的話,使用者在瀏覽器中檢視到的所有image、css或js資源都是處在http://127.0.0.1/static下的。
django靜態檔案的絕對路徑是根據自己的實際情況來確定的,一般在自己的django的app名/static目錄下,或自己python manage.py collectstatic後的路徑下。像我的是在/wwwroot/destiny/destiny/static根目錄下。
“location /”是指訪問專案根目錄時,nginx要做的事。其中需要指定 uwsgi_params檔案的絕對路徑,上面已經提到了;如果還有media檔案之類的靜態目錄,仿照static的寫法,自己補充。
127.0.0.1:9090是指uWSGI繫結的監聽地址,這裡使用了9090埠。
需要注意的是,請確認自己django的靜態檔案目錄所有者是www使用者,如果不是,請用以下命令更改靜態目錄許可權歸屬者:

1 sudo chown -R www:www /wwwroot/destiny/destiny/static

下面接著建立uWSGI的配置檔案在自己工程目錄下建立uwsgi.ini檔案,寫入以下內容

 1 [uwsgi]
 2 socket = 127.0.0.1:9090
 3 chdir=/wwwroot/destiny
 4 module=destiny.wsgi
 5 master = true         
 6 processes=2
 7 threads=2
 8 max-requests=2000
 9 chmod-socket=664
10 vacuum=true
11 daemonize = /wwwroot/destiny/uwsgi.log

其中的socket欄位值”127.0.0.1:9090”必須要和上面寫的density.conf配置檔案中的uWSGI監聽地址完全一樣;
chdir指自己工程的絕對路徑;
module指的是wsgi.py在自己工程中的相對路徑,”.”指代一層目錄;我的django工程的wsgi.py檔案是在”/wwwroot/destiny/destiny/wsgi.py”,所以寫成destiny.wsgi;
daemonize指定uWSGI日誌的儲存路徑。

好了,現在理一下路徑:

1 工程路徑:                  /wwwroot/destiny
2 工程靜態檔案路徑:            /wwwroot/destiny/destiny/static
3 wsgi.py的路徑:             /wwwroot/destiny/destiny/wsgi.py
4 uwsgi.ini的路徑:           /wwwroot/destiny/uwsgi.ini
5 uwsgi日誌路徑:             /wwwroot/destiny/uwsgi.log
6 destiny.conf的路徑:        /wwwroot/destiny/destiny.conf
7 uwsgi_params的路徑:        /etc/nginx/conf/uwsgi_params
8 nginx訪問日誌路徑:          /wwwroot/destiny/nginx_access.log
9 nginx錯誤日誌路徑:          /wwwroot/destiny/nginx_error.log

可以發現,我幾乎把所有有關工程的配置檔案和日誌檔案都放在工程目錄下了,方便後期維護與查錯。

啟動uWSGI

1 sudo uwsgi --ini /wwwroot/destiny/destiny.ini

啟動nginx
在這之前,我們要先去nginx配置檔案的根目錄拷貝mime.types(/etc/nginx/conf/mime.types)到工程目錄(/wwwroot/destiny/mime.types),和destiny.conf放在一起
否則用配置檔案啟動nginx會報錯:

1 nginx: [emerg] open() "/**/**/**/mime.types" failed (2: No such file or directory)

當然,如果不想拷貝mime.types檔案,也可以將配置檔案中“include mime.types;”一項,改成絕對路徑“include /etc/nginx/conf/mime.types;”
如果nginx已經開啟,先關閉nginx(service nginx stop或nginx -s stop),再執行以下命令:

1 nginx -c /wwwroot/destiny/destiny.conf

這裡的-c 表示載入配置檔案啟動

三、後記

到這裡,工作基本就做完了,可以開啟瀏覽器,輸入自己專案的IP地址,如http://127.0.0.1/檢視效果了。

  1. 如果啟動時就報錯,檢視終端資訊,解決錯誤。
    如果終端沒有報錯,但是瀏覽時出現500、502等錯誤,就去專案目錄檢視nginx日誌和uWSGI日誌,解決錯誤。
  2. 自己在部署時,遇到很多坑,網上的教程大多附帶virtualenv和supervisor的部署,但是連最基本的部署都說不明白,部署出來的東西效能再好也沒指導意義。基於自己踩坑脫坑的過程,寫下此文。
  3. 正如以上所說,我只是用單獨的一個conf檔案,在nginx上部署了一個工程,沒有說明部署多個工程的問題;也沒有使用virtualenv開發環境、使用supervisor來管理程序等。請根據個人愛好和需要去實踐擴充套件。

更多精彩內容掃碼關注個人公眾號帶你成為IT精英


—— —— —— —— — END —— —— —— —— ————

       歡迎掃碼關注我的公眾號

          爬神養成記