Ubuntu16.04+Anaconda2+nginx+gunicorn+flask+supervisor
概述:
把Python的Flask框架開(kāi)發(fā)的Web應(yīng)用,在Ubuntu上用gunicorn部署起來(lái),用supervisor實(shí)現(xiàn)進(jìn)程守護(hù),用nginx實(shí)現(xiàn)代理和負(fù)載均衡。其中的python使用的是anaconda2 這個(gè)集成包里的。并在anaconda創(chuàng)建的虛擬環(huán)境中運(yùn)行應(yīng)用。關(guān)于虛擬環(huán)境的解釋見(jiàn)下文。
當(dāng)然,你也可以不用創(chuàng)建虛擬環(huán)境,直接在個(gè)人用戶下執(zhí)行,只需將下文中虛擬環(huán)境部分改在真實(shí)環(huán)境中執(zhí)行即可。
第一步:安裝anaconda2
-
1.1,下載Anaconda2的.sh安裝包
Anaconda的官網(wǎng)在這里Download Anaconda Now!。與Python相對(duì)應(yīng),Anaconda的版本分為Anaconda2和Anaconda3,大家可以自行下載日常常用的版本,提供32位和64位下載。但下載速度太慢,建議用國(guó)內(nèi)鏡像:
下載地址 Index of /anaconda/archive/選擇相應(yīng)的版本進(jìn)行下載就好。
linux 下載下來(lái)是一個(gè)*.sh文件
-
1.2,安裝anaconda并配置源
安裝Anaconda建議不要用root用戶,即安裝在自己的個(gè)人家目錄下即可:
bash *.sh
安裝一路按確認(rèn)Yes即可。安裝完成之后會(huì)在家目錄下出現(xiàn)文件夾:
~/Anaconda2/ (以anaconda2為例)
注意安裝過(guò)程中最后會(huì)問(wèn)是否配置環(huán)境變量,記得選擇yes,如果錯(cuò)過(guò)了,則需要手動(dòng)配置環(huán)境變量
echo ‘export PATH="~/anaconda2/bin:$PATH"’ > ~/.bashrc
source ~/.bashrc
在anaconda中,conda install 命令也可以下載python庫(kù),類似于pip
首先,由于默認(rèn)的源地址在國(guó)外較慢,我們需要修改其包管理鏡像為國(guó)內(nèi)源。
Tsinghua Open Source Mirror
簡(jiǎn)單來(lái)說(shuō)就是在終端中運(yùn)行這兩個(gè)命令就好了:
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config --set show_channel_urls yes
執(zhí)行完上述命令后,會(huì)生成~/.condarc(Linux/Mac)或C:\Users\USER_NAME.condarc文件,記錄著我們對(duì)conda的配置,直接手動(dòng)創(chuàng)建、編輯該文件是相同的效果。
而pip的源修改如下:修改~/.pip/pip.conf,沒(méi)有則創(chuàng)建
[global]
index-url = http://pypi.douban.com/simple
trusted-host = pypi.douban.com
timeout = 120
第二步:用anaconda開(kāi)啟一個(gè)虛擬環(huán)境
虛擬環(huán)境是一個(gè)將不同項(xiàng)目所需求的依賴分別放在獨(dú)立的地方的一個(gè)工具,它給這些工程創(chuàng)建虛擬的Python環(huán)境。它解決了“項(xiàng)目X依賴于版本1.x,而項(xiàng)目Y需要項(xiàng)目4.x”的兩難問(wèn)題,而且使你的全局site-packages目錄保持干凈和可管理。比如,你可以工作在一個(gè)需求Django 1.3的工程,同時(shí)維護(hù)一個(gè)需求Django 1.0的工程。
-
2.1,創(chuàng)建虛擬環(huán)境
python中可以用virtualenv創(chuàng)建虛擬環(huán)境,而我們安裝的anaconda也有這個(gè)功能,創(chuàng)建一個(gè)名為 test1 的虛擬環(huán)境,并為這個(gè)虛擬環(huán)境添加flask庫(kù)
conda create -n test1 flask
-
2.2,激活虛擬環(huán)境
source activate test1
進(jìn)入虛擬環(huán)境之后,命令行用戶名前會(huì)出現(xiàn)一個(gè)括號(hào),括號(hào)內(nèi)是該虛擬環(huán)境的名字,表示這是在虛擬環(huán)境中
第三步:用flask框架構(gòu)建一個(gè)簡(jiǎn)單的web應(yīng)用
新建一個(gè)目錄,webtest1,內(nèi)新建一個(gè)python文件webtest.py
直接vim編輯
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#webtest.py
from flask import Flask,request
app = Flask(__name__)
@app.route('/')
def home():
return "home"
if __name__ == '__main__':
app.run(debug=False)
此時(shí)運(yùn)行該py文件,即開(kāi)啟了該web應(yīng)用,如圖所示,輸入http://127.0.0.1:5000/,即可顯示home界面
此時(shí),只能本地訪問(wèn),如果要實(shí)現(xiàn)局域網(wǎng)訪問(wèn),則需修改webtest.py:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#webtest.py
from flask import Flask,request
app = Flask(__name__)
@app.route('/')
def home():
return "home"
if __name__ == '__main__':
app.debug=False
app.run(host='0.0.0.0')
此時(shí),在同局域網(wǎng)的電腦瀏覽器中輸入運(yùn)行該代碼的機(jī)器ip:5000,則顯示home界面
截止這一步,其實(shí)我們簡(jiǎn)單完成了webapi的部署。下面的步驟都是輔助性的,目的在于提高性能,讓這個(gè)web應(yīng)用不容易崩。
第四步:安裝運(yùn)行g(shù)unicorn
gunicorn是一個(gè)WSGI服務(wù)器,類似于JAVA中的tomcat。上一步中我們使用的是flask 自帶的服務(wù)器,完成了 web 服務(wù)的啟動(dòng)。生產(chǎn)環(huán)境下,flask 自帶的服務(wù)器,無(wú)法滿足性能要求。我們這里采用 gunicorn 做 wsgi容器,用來(lái)部署 python。
-
4.1,在虛擬環(huán)境下安裝gunicorn
pip install gunicorn
-
4.2,用gunicorn運(yùn)行web應(yīng)用
gunicorn tmp/webtest1/webtest:app
webtest對(duì)應(yīng)的是py文件名,app對(duì)應(yīng)的是文件中Flask的實(shí)現(xiàn)名,這里默認(rèn)開(kāi)啟的是8000端口。
我這里使用了-b 0.0.0.0:8001 指定了端口,因?yàn)槟J(rèn)的8000端口已被占用
此時(shí)訪問(wèn)結(jié)果如下
第五步:安裝配置nginx
什么是nginx,nginx和gunicorn的區(qū)別
nginx是一個(gè) HTTP 服務(wù)器, 它關(guān)心的是 HTTP 協(xié)議層面的傳輸和訪問(wèn)控制,所以在 Apache/Nginx 上你可以看到代理、負(fù)載均衡等功能??蛻舳送ㄟ^(guò) HTTP Server 訪問(wèn)服務(wù)器上存儲(chǔ)的資源(HTML 文件、圖片文件等等)。通過(guò) CGI 技術(shù),也可以將處理過(guò)的內(nèi)容通過(guò) HTTP Server 分發(fā),但是一個(gè) HTTP Server 始終只是把服務(wù)器上的文件如實(shí)的通過(guò) HTTP 協(xié)議傳輸給客戶端。
而上面所說(shuō)的gunicorn,是應(yīng)用服務(wù)器,是一個(gè)應(yīng)用執(zhí)行的容器。它首先需要支持開(kāi)發(fā)語(yǔ)言的 Runtime(對(duì)于 Tomcat 來(lái)說(shuō)就是 Java,對(duì)gunicorn來(lái)說(shuō)就是python),保證應(yīng)用能夠在應(yīng)用服務(wù)器上正常運(yùn)行。其次,需要支持應(yīng)用相關(guān)的規(guī)范,例如類庫(kù)、安全方面的特性。對(duì)于 Tomcat 來(lái)說(shuō),就是需要提供 JSP/Sevlet 運(yùn)行需要的標(biāo)準(zhǔn)類庫(kù)、Interface 等。為了方便,應(yīng)用服務(wù)器往往也會(huì)集成 HTTP Server 的功能,但是不如專業(yè)的 HTTP Server 那么強(qiáng)大,所以應(yīng)用服務(wù)器往往是運(yùn)行在 HTTP Server 的背后,執(zhí)行應(yīng)用,將動(dòng)態(tài)的內(nèi)容轉(zhuǎn)化為靜態(tài)的內(nèi)容之后,通過(guò) HTTP Server 分發(fā)到客戶端。
作者:Leh
鏈接:https://www.zhihu.com/question/32212996/answer/55169095
來(lái)源:知乎
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處
-
5.1,安裝nginx
sudo apt-get install nginx
nginx的配置文件在 /etc/nginx/sites-available/里,默認(rèn)的是default文件,如果沒(méi)有,則創(chuàng)建default。
server { listen 80; server_name 127.0.0.1; location / { try_files $uri @gunicorn_proxy; } location @gunicorn_proxy { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; proxy_pass http://127.0.0.1:8000; proxy_connect_timeout 500s; proxy_read_timeout 500s; proxy_send_timeout 500s; } }
-
5.2,啟動(dòng)nginx或重啟nginx (restart)
service nginx start
關(guān)于nginx的詳細(xì)配置可參考如下:
http://www.lxweimin.com/p/fd25a9c008a0
http://www.lxweimin.com/p/3e2b9964c279
第六步:supervisor進(jìn)程守護(hù)
嚴(yán)重推薦這篇介紹 :使用 supervisor 管理進(jìn)程
Supervisor (http://supervisord.org) 是一個(gè)用 Python 寫(xiě)的進(jìn)程管理工具,可以很方便的用來(lái)啟動(dòng)、重啟、關(guān)閉進(jìn)程(不僅僅是 Python 進(jìn)程)。
除了對(duì)單個(gè)進(jìn)程的控制,還可以同時(shí)啟動(dòng)、關(guān)閉多個(gè)進(jìn)程,比如很不幸的服務(wù)器出問(wèn)題導(dǎo)致所有應(yīng)用程序都被殺死,此時(shí)可以用 supervisor 同時(shí)啟動(dòng)所有應(yīng)用程序而不是一個(gè)一個(gè)地敲命令啟動(dòng)。
-
6.1,安裝supervisor(不在虛擬環(huán)境里)
pip install supervisor 或者使用 sudo apt-get install supervisor
-
6.2,配置文件 supervisor.conf
用以下命令可以把默認(rèn)的配置生成到制定位置
echo_supervisord_conf > /your_file_path/supervisord.conf
如果是使用apt-get安裝的,那么 這個(gè)supervisord.conf文件會(huì)在 /etc/supervisor/文件夾下自動(dòng)生成
; supervisor config file
[unix_http_server]
file=/var/run/supervisor.sock ; (the path to the socket file)
chmod=0700 ; sockef file mode (default 0700)
[supervisord]
logfile=/var/log/supervisor/supervisord.log ; (main log file;default $CWD/supervisord.log)
pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
childlogdir=/var/log/supervisor ; ('AUTO' child log dir, default $TEMP)
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[supervisorctl]
serverurl=unix:///var/run/supervisor.sock ; use a unix:// URL for a unix socket
[include]
files = /etc/supervisor/conf.d/*.conf
配置文件最后一行,設(shè)置的是要運(yùn)行的進(jìn)程的配置文件路徑,可見(jiàn)只要后綴名是conf即可被識(shí)別,于是新建文件/etc/supervisor/conf.d/webapi.conf
[program:webtest]
directory = /home/bigdata/Project_2017/webapi/ ; 程序的啟動(dòng)目錄
command =/home/bigdata/anaconda2/bin/gunicorn -k gevent -t 300 run:app ; 啟動(dòng)命令,可以看出與手動(dòng)在命令行啟動(dòng)的命令是一樣的
autostart = true ; 在 supervisord 啟動(dòng)的時(shí)候也自動(dòng)啟動(dòng)
startsecs = 5 ; 啟動(dòng) 5 秒后沒(méi)有異常退出,就當(dāng)作已經(jīng)正常啟動(dòng)了
autorestart = true ; 程序異常退出后自動(dòng)重啟
startretries = 3 ; 啟動(dòng)失敗自動(dòng)重試次數(shù),默認(rèn)是 3
user = root ; 用哪個(gè)用戶啟動(dòng)
redirect_stderr = true ; 把 stderr 重定向到 stdout,默認(rèn) false
stdout_logfile_maxbytes = 20MB ; stdout 日志文件大小,默認(rèn) 50MB
stdout_logfile_backups = 20 ; stdout 日志文件備份數(shù)
; stdout 日志文件,需要注意當(dāng)指定目錄不存在時(shí)無(wú)法正常啟動(dòng),所以需要手動(dòng)創(chuàng)建目錄(supervisord 會(huì)自動(dòng)創(chuàng)建日志文件)
stdout_logfile = /home/bigdata/tmp/usercenter_stdout.log
; 可以通過(guò) environment 來(lái)添加需要的環(huán)境變量,一種常見(jiàn)的用法是修改 PYTHONPATH
; environment=PYTHONPATH=$PYTHONPATH:/path/to/somewhere
自行修改以上配置
-
6.3,設(shè)置并啟動(dòng)supervisord(服務(wù)端)
首先,supervisord運(yùn)行是需要有配置文件的,啟動(dòng)supervisord可以直接命令行運(yùn)行
supervisord
這時(shí),supervisor會(huì)默認(rèn)依次在這幾個(gè)路徑下尋找配置文件
$CWD/supervisord.conf,
$CWD/etc/supervisord.conf,
/etc/supervisord.conf
如果這幾個(gè)路徑下沒(méi)有該配置文件,則啟動(dòng)失敗。
所以如果配置文件在其他位置例如/your_file_path/supervisord.conf ,則需要用 -c 設(shè)置
supervisord -c /your_file_path/supervisord.conf
-
6.4,啟動(dòng)supervisorctl(客戶端)
命令
sudo supervisorctl -c /your_file_path/supervisord.conf
這里客戶端和服務(wù)端要使用同一個(gè)supervisord.conf文件,要確保兩者使用的是同一個(gè)!要么都默認(rèn)位置,要么都指定同一位置。
這樣就可以進(jìn)入supervisor客戶端
這里的web應(yīng)用是對(duì)應(yīng)的/etc/supervisor/conf.d/webapi.conf文件里的配置的,我的配置文件有兩個(gè)即
webapp 和 webtest
這樣,web接口進(jìn)程就被supervisor守護(hù)了,關(guān)掉終端也無(wú)所謂了。
如果要關(guān)閉應(yīng)用進(jìn)程,則進(jìn)入supervisorctl
里面有stop;start;restart等命令,后跟web應(yīng)用名即可
參考文獻(xiàn):
https://zhuanlan.zhihu.com/p/21262280
http://www.lxweimin.com/p/be9dd421fb8d
https://gist.github.com/binderclip/f6b6f5ed4d71fa64c7c5
http://www.cnblogs.com/Ray-liang/p/4837850.html
http://liyangliang.me/posts/2015/06/using-supervisor/
https://www.zhihu.com/question/32212996
PS:錯(cuò)誤之處還請(qǐng)指正,謝謝!