flask能夠快速的搭建http服務,可是爲了搭建網站仍是須要web服務器和相關監控管理操做,一套flask、uwsgi、supervisor、nginx是較好的完整解決方案。html
本文對本身學習作一個記錄,以一個簡單的顯示‘Hello Flask!’程序來測試,跑通整個流程,方式是在局域網服務器上部署,在我的電腦上訪問。python
服務器系統是centos7 安裝了pyenv pyenv 切換到python3.5版本,不懂版本切換的能夠參考我這邊文章https://www.jianshu.com/p/492853d0e683nginx
新建一個簡單程序test_flask.py
from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello Flask!' if __name__ == '__main__': app.run(host='0.0.0.0',port=8080)
測試局域網訪問
在服務器上運行# python test_flask.py,出現以下: 此時,在我的電腦瀏覽器輸入10.12.28.27:8080,(10.12.28.27是我服務器ip),出現以下錯誤: ok,此時緣由多是服務器防火牆打開了,須要關閉,在服務器上輸入關閉防火牆命令(注意系統不一樣命令也不一樣): 關閉後,在我的電腦瀏覽器輸入10.12.28.27:8080,出現hello,Flask!(注意web進程必定要設置ip:0.0.0.0,公網才能訪問到) ##搭建uWSGI服務 Flask 是一個 Web 應用框架,框架的做用在於處理 request 和 reponse,使用的是 Python 自帶的 simple HTTPServer 建立的,在安全性和效率上都是不行的,而uWSGI 是一個全功能的 HTTP 服務器,他要作的就是把 HTTP 協議轉化成語言支持的網絡協議。好比把 HTTP 協議轉化成 WSGI 協議,讓 Python 能夠直接使用。 uwsgi 是一種 uWSGI 的內部協議,使用二進制方式和其餘應用程序進行通訊。 如今,咱們結束上面的flask服務,在服務器上安裝uWSGI,直接輸入以下命令web
pip install uwsgiflask
安裝完,直接輸入啓動命令:centos
uwsgi --http 0.0.0.0:8080 --home env --wsgi-file test_flask.py --callable app --master瀏覽器
出現以下錯誤緩存
Fatal Python error: Py_Initialize: Unable to get the locale encoding ImportError: No module named 'encodings'安全
緣由是--home參數,之前uwsgi須要這個參數來指定python環境變量的目錄,如今不須要這個參數,直接:服務器
uwsgi --http 0.0.0.0:8080 --wsgi-file test_flask.py --callable app --master
運行成功: 在我的電腦瀏覽器輸入10.12.28.27:8080,出現Hello,Flask!(注意uwsgi配置ip:0.0.0.0,公網才能訪問到) 固然,爲了減小輸入命令麻煩,能夠用配置文件來啓動uwsgi, 在當前目錄新建 vi uwsgi_config.ini:
[uwsgi] # uwsgi 啓動時所使用的地址與端口 # socket = 0.0.0.0:8080 # 外網訪問端口,若是直接用uWSGI外網,這裏因爲使用了Nginx,故註釋掉 http= 0.0.0.0:8080 # 指向項目地址 chdir = /root/zlw/web_flask/ # python 啓動程序文件,應該在上面的目錄中 wsgi-file = test_flask.py # python 程序內用以啓動的 application 變量名 # app 是 manage.py 程序文件內的一個變量,這個變量的類型是 Flask的 application 類 callable = app # 處理器數 processes = 4 # 線程數 threads = 2 #狀態檢測地址 stats = 127.0.0.1:9191
配置文件啓動uwsgi(這裏uwsgi_config.ini是在當前目錄下):
uwsgi uwsgi_config.ini
ok,此時,你的應用已經得到了高併發的處理能力,但對於靜態文件的處理uwsgi比較笨拙,而且這種方式安全性也不高,因此要加上Nginx反向代理服務。
在增長Nginx服務以前,咱們還有一個事情要作,考慮一下:我如今有一個進程須要每時每刻不斷的跑,可是這個進程又有可能因爲各類緣由有可能中斷。當進程中斷的時候我但願能自動從新啓動它,此時,我就須要使用到了Supervisor,supervisor管理進程,是經過fork/exec的方式將這些被管理的進程看成supervisor的子進程來啓動,因此咱們只須要將要管理進程的可執行文件的路徑添加到supervisor的配置文件中就行了。此時被管理進程被視爲supervisor的子進程,若該子進程異常中斷,則父進程能夠準確的獲取子進程異常中斷的信息,經過在配置文件中設置autostart=ture,能夠實現對異常中斷的子進程的自動重啓。
搭建supervisor進程管理
沒有supervisor以前啓動uwsgi服務是這樣:uwsgi uwsgi_config.ini 如今我準備使用Supervisor,故uwsgi啓動命令僅供測試的時候用。 安裝supervisor:
yum install supervisor
打開全局配置文件(先找到配置文件路徑:find / -name supervisord.conf)
vi /etc/supervisord.conf
在末尾加入:
[program:Test-flask] # 啓動命令入口 command=uwsgi /root/zlw/web_flask/uwsgi_config.ini # 命令程序所在目錄 directory=/root/zlw/web_flask #運行命令的用戶名 user=root autostart=true # supervisor啓動的時候是否隨着同時啓動 autorestart=true # 當程序跑出exit的時候,這個program會自動重啓 startsecs=3 # 程序重啓時候停留在runing狀態的秒數 #日誌地址 stdout_logfile=/root/zlw/web_flask/uwsgi_supervisor.log
supervisor 相關操做:
啓動:supervisord 打開命令行: supervisorctl
命令行中查看命令: help
命令行中查看狀態: status或者
supervisorctl status //查看狀態
supervisorctl stop [進程名] //中止 supervisorctl start [進程名]
輸入命令supervisord啓動,子程序uwsgi服務將隨之啓動。 這個時候輸入: ps -ef | grep uwsgi 能看到運行的uwsgi程序:
在我的電腦瀏覽器輸入10.12.28.27:8080,出現Hello,Flask!(注意uwsgi配置ip:0.0.0.0,公網才能訪問到) supervisor搭建完畢。
搭建Nginx服務
從上面的講解中,咱們知道,uWSGI 能夠起到 Web 服務器的做用,那麼爲何有了 uWSGI 還須要 Nginx 呢?
最廣泛的說法是 Nginx 對於處理靜態文件更有優點,性能更好。其實若是是小網站,沒有靜態文件須要處理,只用 uWSGI 也是能夠的,但加上 Nginx 這一層,優點能夠很具體:
-
對於運維來講比較方便,若是服務器被某個 IP 攻擊,在 Nginx 配置文件黑名單中添加這個 IP 便可,若是隻用 uWSGI,那麼就須要在代碼中修改了。另外一方面,Nginx 是身經百戰的 Web 服務器了,在表現上 uWSGI 顯得更專業,好比說 uWSGI 在早期版本里是不支持 https 的,能夠說 Nginx 更安全。
-
Nginx 的特色是可以作負載均衡和 HTTP 緩存,若是不止一臺服務器,Nginx 基本就是必選項了,經過 Nginx,將資源能夠分配給不一樣的服務器節點,只有一臺服務器,也能很好地提升性能,由於 Nginx 能夠經過 headers 的Expires or E-Tag,gzip 壓縮等方式很好地處理靜態資源,畢竟是 C 語言寫的,調用的是 native 的函數,針對 I/O作了優化,對於動態資源來講,Nginx 還能夠實現緩存的功能,配合 CDN 優化(這是 uWSGI 作不到的)。Nginx 支持epoll/kqueue 等高效網絡庫,可以很好地處理高併發短鏈接請求,性能比 uWSGI 不知道高到哪裏去了。
-
若是服務器主機上運行了PHP,Python 等語言寫的多個應用,都須要監聽80端口,這時候 Nginx 就是必選項了。由於咱們須要一個轉發的服務。 安裝:
yum install nginx
打開全局配置文件(先找到配置文件路徑:find / -name nginx.conf)
vi /etc/nginx/nginx.conf
修改配置:(注意先備份一份)
server { listen 80 default_server; listen [::]:80 default_server; server_name 10.12.28.27; # 這裏是服務域名,請求的url必須包含該字段Nginx才能響應。 #root /usr/share/nginx/html; # Load configuration files for the default server block. # include /etc/nginx/default.d/*.conf; access_log /root/zlw/web_flask/nginx_access.log; # 服務器接收的請求日誌 error_log /root/zlw/web_flask/nginx_error.log; # 錯誤日誌 location / { include uwsgi_params; uwsgi_pass 0.0.0.0:8080; # 指向uwsgi 所應用的內部地址,全部請求將轉發給uwsgi 處理 uwsgi_param UWSGI_CHDIR /root/zlw/web_flask; # 指向網站根目錄 uwsgi_param UWSGI_SCRIPT test_flask:app; # 指定啓動程序
nginx一些操做:
驗證配置是否正確:nginx -t 啓動: nginx 重啓: nginx -s reload 中止: nginx -s quit
啓動後,在我的電腦瀏覽器輸入10.12.28.27:80,出現很卡的想象,一直出不來結果,等很久提示以下:
分析緣由:配置出現問題。 從新設置配置,將默認配置/etc/nginx/nignx.conf還原爲原來的配置。而且默配置文件內有以下配置
include /etc/nginx/conf.d/*.conf;
ok,新建一個配置:
vi /etc/nginx/conf.d/my_nginx.conf
輸入以下內容:
server { listen 80; server_name 10.12.28.27; # 服務器ip, charset utf-8; client_max_body_size 100M; location / { include uwsgi_params; #uwsgi_pass unix:/root/zlw/web_flask/flask_uwsgi.sock; # sock方式跑不通,緣由未知 uwsgi_pass 127.0.0.1:8080; } }
同時,修改以前的uwsgi_config.ini配置文件(注意本身的文件路徑):
vi /root/zlw/web_flask/uwsgi_config.ini
修改成:
[uwsgi] # uwsgi 啓動時所使用的地址與端口 socket = 127.0.0.1:8080 #socket = /root/zlw/web_flask/flask_uwsgi.sock # 經過sock文件的方式行不通,緣由未知 #permissions for the socket file #chmod-socket = 666 # 外網訪問端口,若是直接用uWSGI外網,這裏因爲使用了Nginx,故註釋掉 #http= 127.0.0.1:8080 # 指向項目地址 chdir = /root/zlw/web_flask/ # python 啓動程序文件 wsgi-file = test_flask.py # python 程序內用以啓動的 application 變量名 # app 是 manage.py 程序文件內的一個變量,這個變量的類型是 Flask的 application 類 callable = app # 處理器數 processes = 1 # 線程數 threads = 2 #狀態檢測地址 stats = 127.0.0.1:9191
保存好,重啓supervisor,重啓nginx
在我的電腦瀏覽器輸入10.12.28.27:80,出現Hello,Flask! 輸入10.12.28.27:8080將出現沒法訪問狀況。由於uwsgi 服務ip設置爲127.0.0.1了,其餘電腦沒法訪問,只能經過nginx的監聽端口80進行訪問。若uwsgi 服務指定ip:0.0.0.0:8080,則,其餘電腦輸入10.12.28.27:8080也能從新hello,flask,固然10.12.28.27:80也能(uwsgi配置ip要和nginx配置一致)
到此能跑通也算大功告成了,可是不能知足,當咱們服務器運行了多個flask時該怎麼處理呢,下面咱們就繼續嘗試管理多個進程時的相關配置操做。
##啓動多個Flask進程 咱們分別創建兩個測試項目:
- /root/web_flask
- /root/zlw
每一個項目目錄下分別有文件:
- test_flask1.py,uwsgi_config1.ini,logs/
- test_flask2.py,uwsgi_config2.ini,logs/
test_flask1.py 和test_flask2.py是和上面簡單測試程序同樣的,uwsgi配置啓動端口和檢測端口分別不同。
uwsgi配置 uwsgi_config1.ini:
[uwsgi] # uwsgi 啓動時所使用的地址與端口 socket = 127.0.0.1:8080 # 指向項目地址 chdir = /root/web_flask/ # python 啓動程序文件 wsgi-file = test_flask1.py # python 程序內用以啓動的 application 變量名 # app 是 manage.py 程序文件內的一個變量,這個變量的類型是 Flask的 application 類 callable = app # 處理器數 processes = 1 # 線程數 threads = 2 #狀態檢測地址 stats = 127.0.0.1:9191
uwsgi_config2.ini:
[uwsgi] # uwsgi 啓動時所使用的地址與端口 socket = 127.0.0.1:7070 # 指向項目地址 chdir = /root/zlw/ # python 啓動程序文件 wsgi-file = test_flask2.py # python 程序內用以啓動的 application 變量名 # app 是 manage.py 程序文件內的一個變量,這個變量的類型是 Flask的 application 類 callable = app # 處理器數 processes = 1 # 線程數 threads = 2 #狀態檢測地址 stats = 127.0.0.1:7171
此時測試一下,uwsgi分別啓動項目(注意只能單個分別啓動,ctrl+c結束) uwsgi /root/web_flask/uwsgi_config1.ini uwsgi /root/zlw/uwsgi_config2.ini 分別都能啓動成功,進行supervisor配置,經過supervisor來同時啓動兩個項目。
supervisor配置 個人supervisor默認配置是/etc/supervisor.conf,打開會找到相似這樣的配置
[include] files = supervisord.d/*.ini
所以能夠在/etc/supervisord.d/目錄下的構建兩個進程的配置文件.ini各式。固然也能夠直接在默認配置文件中增長進程配置。 如下是個人配置(增長兩個進程配置文件,同時記得將默認配置文件原來設置的進程配置刪除掉): /etc/supervisord.d/my_flask1.ini
[program:Test-Flask1] command=uwsgi /root/web_flask/uwsgi_config1.ini stdout_logfile=/root/web_flask/logs/supervisor.log autostart=true autorestart=true startsecs=5 # 啓動5秒內沒異常說明啓動成功。 priority=1 # 啓動優先級 stopasgroup=true # 程序被終止是否通知用戶組 killasgroup=true #被kill是否通知用戶組
/etc/supervisord.d/my_flask2.ini
[program:Test-Flask2] command=uwsgi /root/zlw/uwsgi_config2.ini stdout_logfile=/root/zlw/logs/supervisor.log autostart=true autorestart=true startsecs=5 # 啓動5秒內沒異常說明啓動成功。 priority=1 # 啓動優先級 stopasgroup=true # 程序被終止是否通知用戶組 killasgroup=true #被kill是否通知用戶組
啓動supervisord,打開supervisorctl能看到啓動成功。 此時,已經能夠在服務器電腦上分別訪問127.0.0.1:8080和127.0.0.1:7070,都將返回Hello Flask。
配置Nginx 分別爲每一個進程配置一個nginx配置文件,文件目錄/etc/nginx/conf.d/ 有以下文件: web_flask1.conf:(監聽80端口指向127.0.0.1:8080)
server { listen 80; server_name 10.12.28.27; charset utf-8; client_max_body_size 100M; access_log /root/web_flask1/logs/nginx_access.log; # 服務器接收的請求日誌 error_log /root/web_flask1/logs/nginx_error.log; # 錯誤日誌 location / { include uwsgi_params; #uwsgi_pass unix:/root/web_flask/flask_uwsgi.sock; uwsgi_pass 127.0.0.1:8080; } }
web_flask2.conf:(監聽70端口指向127.0.0.1:7070)
server { listen 70; server_name 10.12.28.27; charset utf-8; client_max_body_size 100M; access_log /root/web_flask2/logs/nginx_access.log; # 服務器接收的請求日誌 error_log /root/web_flask2/logs/nginx_error.log; # 錯誤日誌 location / { include uwsgi_params; #uwsgi_pass unix:/root/web_flask/flask_uwsgi.sock; uwsgi_pass 127.0.0.1:7070; } }
好了,配置結束。重啓nginx
在我的電腦瀏覽器輸入10.12.28.27:80,出現Hello,Flask! 在我的電腦瀏覽器輸入10.12.28.27:70,出現Hello,Flask!