【Flask】 利用uWSGI和Nginx發佈Flask應用html
默認已經準備好python環境而且已經安裝好了flask python
一 安裝uwsginginx
二 安裝nginxweb
http://www.javashuo.com/article/p-eeysafjq-dm.htmlsql
由於Flask比較容易上手,以前也拿flask寫過幾個小項目,不過當時天真地覺得只要在服務器上nohup跑一個python腳本就算是成功發佈了這個flask項目。實際上這還面臨不少問題,好比並發性很差,不支持異步(雖然也能夠在run裏面加上threaded之類的參數來解決,但終究不是正途)等等。真正通用的作法應該是用某些web容器來啓動項目。接下來講明作法,整個過程主要參考了這篇文章(https://segmentfault.com/a/1190000004294634)json
我測試部署的系統是CentOS7 x86_64,環境搭建部分(包括安裝python,安裝flask以及flask相關依賴)的工做就跳過了。從安裝uWSGI開始講起。flask
■ uwsgi的安裝和配置 segmentfault
uWSGI是一個由python實現的web容器,能夠兼容性比較好地發佈Django,Flask等pythonweb框架的應用。由於本質上來講uwsgi是python的一個模塊,因此能夠用pip install uwsgi直接來安裝它。瀏覽器
安裝完成以後能夠在一個合適的目錄創建一個uwsgi服務器的配置文件。好比我選擇在項目的根目錄創建了一個uwsgiconfig.ini的文件。順便一提,除了ini格式的配置,uwsgi還支持json,xml等多種多樣的配置格式。這裏以ini格式爲例。安全
一個典型的配置文件以下:
[uwsgi] socket = 127.0.0.1:5051 pythonpath = /home/wyz/flask module = manage wsgi-file = /home/wyz/flask/manage.py callable = app processes = 4 threads = 2 daemonize = /home/wyz/flask/server.log
依次解釋一下這些配置項。socket指出了一個套接字,至關於爲外界留出一個uwsgi服務器的接口。須要注意的是,socket不等於http。換句話說用這個配置起來的uwsgi服務器是沒法直接經過http請求成功訪問的,這一點後面還會提到,是遇到的一個坑。
pythonpath指出了項目的目錄,module指出了項目啓動腳本的名字而緊接着的wsgi-file指出了真正的腳本的文件名。callable指出的是具體執行.run方法的那個實體的名字,通常而言都是app=Flask(__name__)的因此這裏是app。processes和threads指出了啓動uwsgi服務器以後,服務器會打開幾個並行的進程,每一個進程會開幾條線程來等待處理請求,顯然這個數字應該合理,過小會使得處理性能很差而太大則會給服務器自己帶來太大負擔。daemonize項的出現表示把uwsgi服務器做爲後臺進程啓動,項的值指向一個文件代表後臺中的全部輸出都重定向到這個日誌中去。
以上這些配置項都是一些最爲常見的配置項,實際上uwsgi還有不少不少配置。。除了寫一個配置文件的啓動方式以外,還有命令行的啓動方式,這裏就很少說了。請須要的本身百度。。【抱歉】
此外上面也說到此次碰到的一個坑,就是關於socket和http的差異。從概念上來講,socket自己不是協議而是一種具體的TCP/IP實現方式,而HTTP是一種協議且基於TCP/IP。具體到這個配置這裏來,若是我只配了socket = 127.0.0.1:5051的話,經過瀏覽器或者其餘HTTP手段是沒法成功訪問的。而在uwsgi這邊的日誌裏會提示請求包的長度超過了最大固定長度。另外一方面,若是配置的是http = 127.0.0.1:5051的話,那麼就能夠直接經過通常的http手段來訪問到目標。但這會引發nginx沒法正常工做。正確的作法應該是,若是有nginx在uwsgi以前做爲代理的話應該配socket,而若是想讓請求直接甩給uwsgi的話那麼就要配http。
配置完成以後就能夠鍵入 uwsgi 配置文件.ini來啓動uwsgi,再查看日誌(若是配置了daemonize的話)若是最終沒有報錯,ps也能看到processes指定個數的uwsgi進程在跑的話說明成功啓動。若是直接把uwsgi做爲留給外部的鏈接接口發佈應用的話固然也能夠,可是通常而言咱們確定還要在uwsgi前面再加上一個nginx。nginx的好處在於能夠進行安全過濾,防DDOS攻擊,多臺機器的負載均衡等工做。
關於uwsgi服務器的中止,官方文檔說能夠uwsgi -HUP之類的命令操做,可是這須要找到這個uwsgi的pid,目前爲止我都仍是很粗暴地killall -9 uwsgi了。。
■ nginx的安裝和配置
最開始用yum install nginx裝了好多此仍是報缺乏libpcre.so.0的錯,網上搜了一通發現多是由於我用的是CentOS7版本的系統而yum源中仍是適用於CentOS6的包。因此不如去網上找個rpm包或者直接下個源碼包來編譯安裝。。。
nginx經常使用命令:
nginx 啓動nginx
nginx -s stop/reload 中止nginx/重載配置文件
nginx -v 查看版本
nginx -t 測試配置文件是否有語法上的錯誤等
安裝完成後默認的nginx的配置文件位於/etc/nginx/conf.d/default.conf,我直接修改了這個文件。在修改以前能夠考慮先備個份。若是須要指定配置文件開啓nginx能夠加入-c參數。其實nginx默認讀取的文件是/etc/nginx/nginx.conf,打開這個文件看看能夠看到在其http塊中有些include /etc/nginx/conf.d/*.conf,因此在那裏的default.conf能夠直接寫server塊。
以前也瞭解過一點關於nginx的配置問題,其要義大概就是nginx的配置文件格式比較要緊,好比要有大括號,句尾有分號等等。另外以#開頭的行都是註釋,均可以不用管。在nginx的這個配置中咱們主要修改如下內容:
server { listen 80; //默認的web訪問端口 server_name xxxxxx; //服務器名 #charset koi8-r; access_log /home/wyz/flask/logs/access.log; //服務器接收的請求日誌,logs目錄若不存在須要建立,不然nginx報錯 error_log /home/wyz/flask/logs/error.log; //錯誤日誌 location / { include uwsgi_params; //這裏是導入的uwsgi配置 uwsgi_pass 127.0.0.1:5051; //須要和uwsgi的配置文件裏socket項的地址 //相同,不然沒法讓uwsgi接收到請求。 uwsgi_param UWSGI_CHDIR /home/wyz/flask; //項目根目錄 uwsgi_param UWSGI_SCRIPT manage:app; //啓動項目的主程序(在本地上運行 //這個主程序能夠在flask內置的 //服務器上訪問你的項目) } }
這樣配置完後,當外部有一個80端口的請求送到本機時,先讓nginx開始處理。nginx進行一些處理以後轉發給這裏配置的uwsgi_pass地址,恰好傳送給uwsgi處理。再由uwsgi來調用項目中的代碼處理請求返回。再來回味一下上面那個坑,若是當時僅僅配了一個http項而沒有配置socket的話,就會致使一切容器啓動都順利,可是當我把請求發送給80端口的時候遲遲不來響應,直到超時。
* 經網友提醒,這實際上是一個Nginx和uWSGI之間配置協同的一個問題。若是uWSGI直接經過HTTP方式對外提供服務,那麼nginx中須要配置proxy_pass,指出HTTP服務具體套接字,從而實現請求的轉發(參考zabbix安裝時的nginx配置就是這樣的)。而若是將uWSGI配置爲socket,經過socket對外提供服務(因爲socket不涉及具體的協議,外部無法直接經過uWSGI端口訪問服務也更加安全一些。好比能夠在nginx中配置一些URL的拒接防止sql注入之類的),那麼nginx配置就應該得是uwsgi_pass來實現請求的轉發。 proxy_pass配置的時候寫http://,即表示是走http協議的;uwsgi_pass的時候未指出協議,表示走socket。