接觸了flask開發有一小段時間了,使用flask主要完成了咱們產品的Android客戶端的後臺服務(提供REST API),還有就是爲運營提供數據統計及應用發佈的web系統。以前都是經過傳統的筆記原本記錄開發中遇到的問題,漸漸發現不少問題存在着不少的共性,經過博客的方式開啓一個記錄和交流的新方法吧。文中若是有什麼錯誤歡迎指出,對flask開發有興趣的朋友也能夠互相交流,探討問題。html
flask在他的官方文檔中是這樣描述的,flask是一個python的微框架,基於Werkzeuk和Jinjia2。目前對於python2和python3的支持都很好。入門也很簡單,強烈推薦官方文檔,例子簡單清楚。官方文檔.另一個參考的就是《FlaskWeb開發:基於Python的Web應用開發實戰》在網上能夠找到不少電子版的,經過官方的文檔能夠了解flask是什麼以及如何開始一個hello word,而經過上面提到第二個參考資料,能夠實現一個簡單的博客系統,更好的瞭解flask的。在這裏就很少介紹如何開始flask開發的,我感受官方的文檔已經介紹的足夠簡單清楚,這些內容也不是本文的主要內容,本文的焦點主要放在如何實現flask的部署,以及分享我在部署過程當中遇到的問題,以及通過這些折騰以後個人建議吧。python
系統: centos 6.5 x86_64linux
python: 版本3.5.2nginx
flask:用來實現REST API及相關的web功能, 版本0.11web
celery : 一個很好的分佈式管理隊列,在個人應用場景中主要使用它來作一些定時的任務,其實主要是定時向咱們的運維人員發送一些日誌及告警信息。shell
官方文檔.版本3.1.24flask
gunicorn : 做爲flask應用的web server,自帶的web server是用來咱們開發和測試過程當中進行調試的,是一個單進程單線程的,沒法作生產部署只用,centos
以前嘗試過uwsgi做爲web server,可是從部署角度來講,gunicorn配置更加方便,另外,gunicorn 對於gevent的支持也是很是不錯的,服務器
因此綜合以上兩個緣由,才用的gunicorn做爲web server部署。官方配置文檔, 版本19.6網絡
gevent: 一個很好的基於協程的python網絡庫,能夠很容易的提高系統的併發性,並且gunicorn對gevent的支持也很好,配置簡單。官方文檔, 版本1.2
nginx: 用做反向代理, 版本1.6.2
supervisord: 用以管理個人flask應用以及celery任務。gunicorn已經能夠實現將本身做爲一個守護進程,從必定程度上來講,即便不適用supervisord也沒有任何
問題,可是celery在centos 6.5上配置自啓動以及變成守護進程相對麻煩,另外從統一管理及維護簡單的角度來考慮,採用supervisord也是一個不錯
的選擇。不得不說下,在使用supervisord以前,都是手動殺gunicorn的進程的。一樣附上官方文檔.版本3.3.1
我再囉嗦一下,爲何每一個都附上了官方的文檔,由於我在個人部署過程當中遇到過很多的問題,搜索過到不少其餘人分享的東西,發現不少別人分享的東西都有特定的版本限制,而一般過程當中,做者並無寫清楚他當時使用的版本,而對於一個開始接觸這種部署方式的人來講,調錯是一件耗時耗力的事情,雖然過程當中咱們能夠經過解決問題提高本身,但從我我的的感覺來看,若是第一次配置部署中出現了難以解決的問題,極可能會迫使你轉用其餘的方式,因此官方文檔給的配置說明是最清晰的。
1、必定使用Python虛擬環境(即virtualenv),爲何這麼說呢,從部署的角度來講,方便,易維護,若是服務器上有多個版本的python或者當你使用Python3 來開發項目,而後使用跟我同樣的部署方式的時候你就會跟我有同樣的體會。
一、安裝virtualenv: yum install virtualenv
二、進入到你的工程目錄,我的建議把虛擬環境放到你的工程目錄當中,保證每個工程有本身獨立的python環境,
在shell中執行: virtualenv -p python3 venv 來建立虛擬環境,其中 -p 參數制定python的路徑,執行完以後能夠發如今工程目錄中產生一個
名爲venv的文件夾,之後該虛擬環境全部的擴展包的安裝目錄。
三、安裝Python虛擬環境的全部依賴包:
在開發過程當中能夠經過執行指令 pip freeze > requirement.txt 來導出依賴包及其對應的版本。
在工程目錄中,執行: source venv/bin/activate 進入虛擬環境,這時,在你的shell中應該是以下相似的顯示: (venv) localhost:service allan$
接着經過執行 pip install -r requirement.txt 來安裝全部的擴展包,至此,虛擬環境配置完成。若是須要退出虛擬環境,
能夠在shell中執行 deactivate
在工程目錄中使用flask自帶的web server 運行flask應用,應用功能一切正常。
2、nginx相關配置:
1 location / { 2 proxy_pass http://127.0.0.1:9000; 3 proxy_set_header Host $host; 4 proxy_set_header X-Real-IP $remote_addr; 5 proxy_set_header REMOTE-HOST $remote_addr; 6 proxy_set_header X-Forward-For $proxy_add_x_forwarded_for; 7 proxy_redirect off; 8 }
3、gunicorn已經在第一步虛擬環境的配置的部分的擴展包安裝中完成,其簡單配置以下:
1 import gevent.monkey 2 import multiprocessing 3 4 gevent.monkey.patch_all() 5 6 bind = '0.0.0.0:9000' 7 # restart workers when code change, only use in development 8 #reload = True 10 preload_app = True 12 # debug when development and error when production 13 loglevel = 'error' 14 logfile = 'log/debug.log' 15 accesslog = 'log/access.log' 16 access_log_format = '%(h)s %(t)s %(U)s %(q)s' 17 errorlog = 'log/error.log' 18 # process name 19 proc_name = 'vservice' 21 pidfile = 'log/gunicorn.pid' 22 # set process daemon, not use in default 23 #daemon = True 25 # number of processes 26 workers = multiprocessing.cpu_count() * 2 + 1 27 # number of threads of per process 28 threads = multiprocessing.cpu_count() * 2 29 worker_class = 'gevent'
其中23行的daemon參數的設置是要特殊注意的,若是隻是使用gunicorn而不使用supervisord相似的進程管理工具,該參數設置爲true,使進程成爲守護進程,但一旦使用相似supervisord等進程管理工具時,該參數必定不要設置,gunicorn默認該參數爲False,不然會出現問題。
固然,gunicorn還有不少的參數配置,具體可參考前面部分提供的官方配置文檔部分。
若是單獨使用gunicorn運行,經過指令 gunicorn -c config.py manager:app 來運行,其中manager對應工程目錄中的manager.py, app爲flask應用的名稱。
至此,若是在flask應用中不使用celery也不使用supervisord作進程管理,在必定程度上已經實現了服務器端的部署。到了這裏仍然缺乏一個很重要的環節,那就是監控,我是經過在跟服務器不一樣網絡的一臺測試機器上部署了一個模仿正常客戶端的Python腳原本實現對服務器是否正常工做的檢測,若是連續丟失幾個包會認爲服務器程序異常會向運維人員發送報警的短信及郵件。
4、supervisord配置及安裝:
在虛擬環境的shell中執行 pip install supervisor 安裝supervisord, 我使用的Python版本爲3.5.2, pip安裝以後supervisord的版本爲3.3.1.
安裝完成以後,利用supervisord自帶的命令產生配置文件模板,強烈建議這麼作,由於從網上其餘人的分享中找過來的模板極可能版本不匹配,致使supervisord一直不能正常運行,並且supervisord報的錯誤也會讓你一開始沒有頭緒。
假定在工程目錄中放置你的supervisord配置文件: echo_supervisord_conf /data/vservice/supervisord.conf ,該指令會產生一個你安裝的版本的supervisord對應的模板配置文件。
下面是我在個人工程實踐中的supervisord的配置文件,在模板的基礎上,參考官方文檔各個參數的意義進行的修改:
1 [program:vservice] 2 command=/data/vservicer/venv/bin/gunicorn -c /data/vservice-server/config.py manager:app 3 process_name=%(program_name)s 4 numprocs=1 5 directory=/data/vservice/ 6 autostart=true 7 autorestart=unexpected 8 user=allan 9 stdout_logfile=/data/vservice/log/supervisor/stdout.log 10 stderr_logfile=/data/vservice/log/supervisor/stderr.log 11 12 [program:send_mail] 13 command=/data/vservice/venv/bin/celery worker --app=manager.celery --beat -l INFO 14 process_name=%(program_name)s 15 numprocs=1 16 directory=/data/vservice/ 17 autostart=true 18 autorestart=unexpected 19 stdout_logfile=/data/vservice/log/celery/stdout.log 20 stderr_logfile=/data/vservice/log/celery/stderr.log
首先咱們要測試咱們的配置是否正確,因爲supervisord默認是開啓deamon的,因此在測試supervisord是否正確工做的狀況下咱們先加一個參數,讓supervisord如今前臺工做:
supervisord -c /data/vserver/supervisord.conf -n
這個時候若是你的supervisord若是已經正常工做且沒有錯誤的話,應該會顯示vservice以及send_mail兩個程序進入running狀態,下面是個人輸出,僅供參考:
1 2016-11-04 16:18:31,125 INFO RPC interface 'supervisor' initialized 2 2016-11-04 16:18:31,125 CRIT Server 'unix_http_server' running without any HTTP authentication checking 3 2016-11-04 16:18:31,125 INFO supervisord started with pid 1812 4 2016-11-04 16:18:32,128 INFO spawned: 'send_mail' with pid 1817 5 2016-11-04 16:18:32,129 INFO spawned: 'vservice' with pid 1818 6 2016-11-04 16:18:33,130 INFO success: send_mail entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) 7 2016-11-04 16:18:33,131 INFO success: vservice entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
這個時候你能夠經過supervisorctl 指令查看狀態,啓動,中止或者重啓對應的程序
查看狀態: supervisorctl -c /data/vservice/supervisord.conf status
執行以上指令以後以後顯示的結果:
send_mail RUNNING pid 1911, uptime 0:00:11 vservice RUNNING pid 1912, uptime 0:00:11
中止某個應用: supervisorctl -c /data/vservice/supervisord.conf stop send_mail(或者all或者vservice)
執行以上指令以後以後顯示的結果:
[allan@TEST vservice]# supervisorctl -c /data/vservice/supervisord.conf stop send_mail send_mail: stopped [allan@TEST vservice]# supervisorctl -c /data/vservice/supervisord.conf status send_mail STOPPED Nov 04 04:28 PM vservice RUNNING pid 1912, uptime 0:06:16
啓動某個應用: supervisorctl -c /data/vservice/supervisord.conf start send_mail(或者all或者vservice)
重啓某個應用: supervisorctl -c /data/vservice/supervisord.conf restart send_mail(或者all或者vservice) 一切測試正常以後,如今能夠去掉supervisord的 -n參數,這時候supervisord會變成一個守護進程進入後臺,至此在外部測試你的flask應用是否正常工做便可,部署在這時候已經基本完成。在使用supervisord的過程當中我遇到過很多的問題。一、最開始在網上看到有人說supervisord對Python3的支持目前只是demo階段,還不穩定,當時心涼了一截,後來仔細查各類文檔及別人分享的經驗,發現supervisord 自己運行須要的Python環境是2.x的版本,所以在這個時候Python虛擬環境的重要性再次體現出來:使用2.x的版本環境運行supervisord,可是supervisord自己做爲一個進程管理軟件,它啓動Python3開發的應用用是徹底沒有問題的。二、若是首次使用supervisord 啓動程序出現錯誤,好比exit with code 1, not expected等時,你再次運行supervisord時會報地址端口被佔用的錯誤(在supervisord的錯誤日誌目錄中),這時候你必定記得經過linux的進程管理查看下你的flask 應用是否是已經啓動了,由於極可能出現的狀況是,supervisord已經把你的程序啓動了,可是出現錯誤是在其餘的步驟中,所以你再次啓動時,會出現以上的錯誤狀況。三、supervisord的用戶配置問題,如root帳戶的問題。以上是個人部署過程以及部署過程當中曾經遇到過的問題,固然過程當中也還有其餘的一些小問題,並無一一的在這列出,若是發現有什麼錯誤或者有相關的問題要進行交流討論,能夠經過郵件進行交流:yanhaicheng@gmail.com