centosflask+uWSGI+nginx部署
1. 概念
Flask自帶webserver--Werkzeug,能夠搭建服務,運行網站。但在開發時,通常會用專業的--uWSGI。php
另外,常配合使的還有nginx。html
1.1. uWSGI
uWSGI是一個全站式的託管服務,它實現了應用服務器(支持多種編程語言)、代理、進程管理器、監視器。取名爲uWSGI是由於它最先實現的是Python語言的WSGI。python
WSGI:一種實現python解析的通用接口標準/協議,是一種通用的接口標準或者接口協議,實現了pythonweb程序與服務器之間交互的通用性。linux
利用它,web.py或bottle或者django等等的pythonweb開發框架,就能夠輕鬆地部署在不一樣的webserver上了;nginx
uwsgi:同WSGI同樣是一種通訊協議web
uwsgi協議是一個uWSGI服務器自有的協議,它用於定義傳輸信息的類型,它與WSGI相比是兩樣東西。apache
uWSGI:一種pythonwebserver或稱爲Server/Gatewaydjango
uWSGI相似tornadoweb或者flup,是一種pythonwebserver,uWSGI是實現了uwsgi和WSGI兩種協議的Web服務器,負責響應python的web請求。編程
由於apache、nginx等,它們本身都沒有解析動態語言如php的功能,而是分派給其餘模塊來作,好比apache就能夠說內置了php模塊,讓人感受好像apache就支持php同樣。json
uWSGI實現了wsgi協議、uwsgi協議、http等協議。Nginx中HttpUwsgiModule的做用是與uWSGI服務器進行交換。
uWSGI是C語言寫的,性能比較高。uWSGI包括四個部分:
1.2. Nginx
Nginx是高效的Web服務器和反向代理服務器,能夠用做負載均衡(當有n個用戶訪問服務器時,能夠實現分流,分擔服務器的壓力),能夠進行安全過濾,防DDOS攻擊等。與Apache相比,Nginx支持高併發,能夠支持百萬級的TCP鏈接,十萬級別的併發鏈接,部署簡單,內存消耗少,成本低,但Nginx的模塊沒有Apache豐富。
Nginx支持uWSGI的uwsgi協議,所以咱們能夠將Nginx與uWSGI結合起來,Nginx經過uwsgi_pass將動態內容交給uWSGI處理。
1.3. 爲何要用nginx
既然uWSGI能夠起到Web服務器的做用,那麼爲何有了uWSGI還須要Nginx呢?
最廣泛的說法是Nginx對於處理靜態文件更有優點,性能更好。其實若是是小網站,沒有靜態文件須要處理,只用uWSGI也是能夠的,但加上Nginx這一層,優點能夠很具體:
對於運維來講比較方便,若是服務器被某個IP攻擊,在Nginx配置文件黑名單中添加這個IP便可,若是隻用uWSGI,那麼就須要在代碼中修改了。
另外一方面,Nginx是身經百戰的Web服務器了,在表現上uWSGI顯得更專業,好比說uWSGI在早期版本里是不支持https的,能夠說Nginx更安全。
Nginx的特色是可以作負載均衡和HTTP緩存,若是不止一臺服務器,Nginx基本就是必選項了,經過Nginx,將資源能夠分配給不一樣的服務器節點,只有一臺服務器,也能很好地提升性能,由於Nginx能夠經過headers的ExpiresorE-Tag,gzip壓縮等方式很好地處理靜態資源,畢竟是C語言寫的,調用的是native的函數,針對I/O作了優化,對於動態資源來講,Nginx還能夠實現緩存的功能,配合CDN優化(這是uWSGI作不到的)。Nginx支持epoll/kqueue等高效網絡庫,可以很好地處理高併發短鏈接請求,性能比uWSGI不知道高到哪裏去了。
若是服務器主機上運行了PHP,Python等語言寫的多個應用,都須要監聽80端口,這時候Nginx就是必選項了。由於咱們須要一個轉發的服務。
因此說,Nginx基本也是必選項。因此說雖然uWSGI自己就是一個web服務,這裏再次引入Nginx就是爲了把Nginx做爲一個反向代理,這樣,一些圖片、js等靜態資源就能夠用Nginx提供服務,而其餘的轉發給uWSGI,這也是咱們這套部署架構的最終目的。
2. 部署
2.1. 系統環境
centos6.5
python3.6.5
nginxn 1.10.3
uwsgi 2.0.18
2.2. uWSGI
uWSGI是一個由python實現的web容器,能夠兼容性比較好地發佈Django,Flask等pythonweb框架的應用。由於本質上來講uwsgi是python的一個模塊,因此能夠用pipinstalluwsgi直接來安裝它。
安裝完成以後能夠在一個合適的目錄創建一個uwsgi服務器的配置文件。好比我選擇在項目的根目錄創建了一個uwsgiconfig.ini的文件。順便一提,除了ini格式的配置,uwsgi還支持json,xml等多種多樣的配置格式。這裏以ini格式爲例。
2.2.1. 配置
直接使用uwsgi運行,配置文件以下:
[uwsgi]
http= 0.0.0.0:9000
chdir = /home/web_server/flask/website
wsgi-file= run.py
callable= app
processes=4
threads=2
pidfile = /home/web_server/flask/uwsgi.pid
daemonize = /home/web_server/flask/server.log
各參數說明:
由uwsgi指定了端口後無需再指定flask的運行端口,實際是給出callable變量後,由uwsgi執行run()
socket:套接字通信端口,至關於爲外界留出一個uWSGI服務器的接口,負責與Nginx通訊,但注意socket是沒法直接經過http請求成功訪問。
pythonpath:項目目錄。
callable:程序內啓用的application變量名,通常而言都是app=Flask(__name__)的因此這裏是app。
processes:處理器個數。
threads:線程數。
processes和threads指出了啓動uwsgi服務器以後,服務器會打開幾個並行的進程,每一個進程會開幾條線程來等待處理請求,顯然這個數字應該合理,過小會使得處理性能很差而太大則會給服務器自己帶來太大負擔。
stats:獲取uwsgi統計信息的服務地址
daemonize:使uWSGI進程在後臺運行,並將日誌打到指定的日誌文件或者udp服務器.
2.2.2. 啓動/中止
uWSGI 經過 xxx.ini 啓動後會在相同目錄下生成一個 xxx.pid 的文件,裏面只有一行內容是 uWSGI 的主進程的進程號。
uWSGI 啓動:
uwsgi --ini xxx.ini
uwsgi 重啓:
uwsgi --reload xxx.pid
uwsgi 中止:
uwsgi --stop xxx.pid
pid文件需手動指定生成
2.2.3. 問題
關閉問題
手動指定pid文件後,實際起了4個進程,但pid中只有一個pid,使用—stop關閉也僅關閉pid文件中所記錄的一個進程,其他3個只能kill
批量殺死進程:
pkill uwsgi
pkill -f uwsgi -9 # 通常用不到
2.3. nginx
2.3.1. 安裝
yum install nginx
查看版本
nginx version: nginx/1.10.3
2.3.2. 配置
配置文件的路徑不盡相同,centos上用yum安裝時,通常配置文件在/etc/nginx/nginx.conf
修改nginx.conf配置文件,但這裏不直接修改,而使用另外一種方式(推薦)
默認安裝的Nginx配置文件/etc/nginx/nginx.conf內尾部有以下配置
include /etc/nginx/conf.d/*.conf;
即從外部目錄/etc/nginx/conf.d/文件夾下還引入了其餘配置文件。
這樣,不修改默認配置文件,在/etc/nginx/conf.d/目錄下新增長一個webapp.conf,從而增長配置文件體系健壯性。
webapp.conf內容以下:
server {
listen 9002; //web訪問端口
server_name localhost; //服務器名
charset utf-8;
access_log /var/www/webapp/access.log; //服務器接收的請求日誌,logs目錄若不存在須要建立,不然nginx報錯
error_log /var/www/webapp/error.log; //錯誤日誌
client_max_body_size 100M;
location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:9000; //須要和uwsgi的配置文件裏socket項的地址相同,不然沒法讓uwsgi接收到請求。
#uwsgi_param UWSGI_PYHOME /var/www/webapp/venv;
uwsgi_param UWSGI_CHDIR /home/web_server/flask/web_test; //項目根目錄
#uwsgi_param UWSGI_SCRIPT run:app; //啓動項目的主程序(在本地上運行
//這個主程序能夠在flask內置的
//服務器上訪問你的項目),其實能夠在uwsgi中指定
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
問題:
unknown directive "listen " in
配置文件中有tab空格,用正常空格替換便可。
2.3.3. 啓動/中止
啓動:nginx -c /usr/local/nginx/conf/nginx.conf
中止:
關閉nginx系統方式:
(1)命令
當nginx啓動後,可使用「-s」參數向nginx管理進程(即master進程)發送信號來控制nginx:nginx -s signal
其中,signal能夠是如下值:
[1] stop:快速關閉
[2] quit:安全關閉
[3] reload:重載配置文件
[4] reopen:從新打開一個log文件,主要用於日誌切割
quit信號,通知nginx等待worker進程處理完當前的請求後退出,此命令只能由啓動nginx的linux帳戶來執行。
reload信號,通知nginx從新載入配置文件nginx.conf。 除了使用reload外,nginx只會在啓動時載入一次配置文件,以後對配置文件的修改不會實時對已經運行的nginx進程生效。
當運行這個命令時,master進程會嘗試讀取配置文件,若是配置文件沒有問題(配置文件有問題怎麼驗證呢?請看下文):
master進程會啓動新的worker進程來運行新的配置文件並處理請求,同時會通知老的worker進程再也不處理新的請求並在處理完當前任務後退出。
若是配置文件存在問題不能執行,master進程會回退老配置文件繼續工做,不會致使nginx進程整個異常退出。
linux的kill命令也能夠達到相同的做用,假設nginx的master進程號(pid)是123456,那麼 kill -s QUIT 123456 和 kill -s HUP 123456 這兩條命令和前面quit、reload的做用相同。
關閉nginx命令1:
nginx -s quit
【3】重載配置
從新加載配置文件
(1)命令
nginx -s reload
2.4. uWSGI從新配置
uwsgi獨立運行與使用nginx時的配置不同
配置文件:uwsgi_nginx.ini
[uwsgi]
socket = :9000
chdir = /home/web_server/flask/website
wsgi-file= run.py
callable= app
processes=4
threads=2
pidfile = /home/web_server/flask/uwsgi.pid
daemonize = /home/web_server/flask/server.log
3. 測試結果
3.1. uWSGI
不使用nginx,直接運行uWSGI
uwsgi uwsgi_independent.ini
3.1.1. 結果展現
訪問http://ip:9000/成功。
3.2. uWSGI+ nginx
先啓動uwsgi,若是不寫絕對路徑須要在ini文件當前路徑執行
[root@soft flask]# uwsgi uwsgi_nginx.ini
啓動nginx
nginx -c /etc/nginx/nginx.conf
3.2.1. 結果展現
訪問http://ip:9002/成功。
注意:在配置nginx時指定。
4. 附錄
4.1. 經常使用命令
ps -ef |grep uwsgi
uwsgi uwsgi.ini
uwsgi --stop uwsgi.pid
kill -9