【python應用】flask+gunicorn+nginx+supervisor:在服務器上部署python的web應用

我的生產環境爲Centos7,python3.5。

使用的模塊爲flask+gunicorn+nginx+supervisor。

主要參考了該網址該網址

flask我們已經較熟悉,是一個開發web應用的python模塊。gunicorn用於調用我們的python代碼,符合wgsi的規範。

nginx 是一個高性能的web服務器。通常用來在前端做反向代理服務器。

什麼叫反向代理?舉例如下,你的電腦在局域網,發出一個請求,經過代理服務器到達互聯網中的一個服務器(比如百度的服務器),這個過程叫正向代理。一個來自互聯網的請求,經過代理服務器到達局域網中的一個服務器,這個過程叫反向代理。正向代理是把局域網中的一堆請求收集起來發向互聯網,反向代理是把互聯網發過來的一堆請求分發給局域網的服務器。在正向代理中,代理服務器和客戶端在同一個局域網;在反向代理中,代理服務器和服務器在同一個局域網。

接下來開始具體的工作。

1、設置虛擬環境

虛擬環境是python這種有大量可用輪子的語言必備的。簡而言之就是分給你一塊地,隨便你怎麼折騰,可以安裝各種各樣的模塊。虛擬環境和外面的環境、虛擬環境和虛擬環境之間都不會衝突。很方便。

配置虛擬環境的代碼如下:

cd /home/www
mkdir venv
python3 -m venv venv

首先進入/home/www路徑,新建名爲venv的文件夾,然後使用python中的虛擬環境命令將虛擬環境安裝在venv文件夾中。

python -m venv xxxx 就會把虛擬環境的文件放在這個xxxx文件夾裏面。

之後使用

source venv/bin/activate

激活虛擬環境。現在我們是在www文件夾中,因此source中的路徑包含venv,要是在venv文件夾中,就只需要bin/activate了。

激活成功會在每一行之前有一個(venv),表示目前在虛擬環境中。

想要退出虛擬環境,使用deactivate即可。

2、安裝模塊

flask模塊的安裝在之前已經講過,再次不再贅述。

安裝gunicorn,代碼如下:

pip3 install gunicorn

安裝nginx,代碼如下:

$ yum -y install nginx

原來nginx不是python模塊啊。

3、使用gunicorn調用python

我們使用之前寫的search4web,其代碼如下:

from flask import Flask, render_template,request,redirect
from vsearch import search4letters
 
app=Flask(__name__)
 
'''
@app.route('/')
def hello() -> '302':
    return redirect('/entry')
'''
 
@app.route('/')
@app.route('/entry')
def entry_page() -> 'html':
    return render_template('entry.html',
                           the_title='Welcome to search4letters on the web!')
 
@app.route('/search4',methods=['POST'])
def do_search() -> 'html':
    phrase=request.form['phrase']
    letters=request.form['letters']
    results=str(search4letters(phrase,letters))
    return render_template('results.html',
                           the_title='Here are your results',
                           the_phrase=phrase,
                           the_letters=letters,
                           the_results=results)
 
app.run(debug=True)

爲使用gunicorn調用,最後一行需要更改如下:

if __name__=='__main__':
    from werkzeug.contrib.fixers import ProxyFix
    app.wsgi_app=ProxyFix(app.wsgi_app)
    app.run()

見到熟悉的if __name__=='__main__'了。這就是主函數。然後照着寫就可以 。

使用如下命令調用gunicorn:

gunicorn -w 4 -b 127.0.0.1:8000 vsearch4web:app

這裏的vsearch4web是python文件名,app是文件中的flask實例名。這樣就實現了調用。如果沒有報錯信息說明配置成功,ctrl+c退出。如果有報錯,一般是端口被佔用,利用netstat -ntlp命令查看所有端口號的佔用情況,把佔用8000端口號的進程的PID記錄下來,使用kill -9 進程PID殺掉該進程即可。

該命令表示使用四個線程,當127.0.0.1:8000被訪問的時候調用python。

那麼問題來了,127.0.0.1明顯是一個本地IP而不是一個外部IP,沒法在其他電腦上訪問,這時候就需要nginx出場了。

4、使用nginx進行反向代理

這部分的功能就是當用戶訪問一個固定IP時,轉到gunicorn設置的端口。也就是實現外網對127.0.0.1的間接訪問。

實現這一點,要修改nginx的配置文件。使用如下命令:

cd  /etc/nginx
vi nginx.conf

打開配置文件,按i修改成如下格式:

server {
    listen 8080;
    server_name gumo.online;
 
    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

上述配置的意思是:默認監聽8080端口,也就是當固定IP的8080端口被訪問到時,自動轉向gunicorn的端口,一般不要用默認的80,比如我的80端口就是分給了wordpress;server_name是服務器的名字,既可以寫你自己的公網IP,也可以寫你自己的域名,當然前提是可以通過DNS訪問;接下來的location部分,第一行要保證與gunicorn中的配置相同,接下來兩行照抄即可。注意不要忘了句末分號;。

修改完畢,按下esc,輸入:wq保存並退出。另外說一點,不保存退出是輸入:q!。

保存之後使用nginx -t指令查看配置文件是否保存成功,未成功說明有打錯的地方。

5、nginx與gunicorn的關係

這部分來自該網址

gunicorn 可以單獨提供服務,但生產環境一般不這樣做。首先靜態資源(jscssimg)會佔用不少的請求資源,而對於 gunicorn 來講它本身更應該關注實際業務的請求與處理而不應該把資源浪費在靜態資源請求上;此外,單獨運行 gunicorn 是沒有辦法起多個進程多個端口來負載均衡的。

nginx 的作用就是彌補以上問題,首先作爲前端服務器它可以處理一切靜態文件請求,此時 gunicorn 作爲後端服務器,nginx 將會把動態請求轉發給後端服務器,因此我們可以起多個 gunicorn 進程,然後讓 nginx 作均衡負載轉發請求給多個 gunicorn 進程從而提升服務器處理效率與處理能力。最後,nginx 還可以配置很多安全相關、認證相關等很多處理,可以讓你的網站更專注業務的編寫,把一些轉發規則等其它業務無關的事情交給 nginx 做。

6、啓動服務

建議重新鏈接一下服務器,按如此步驟運行:

cd /home/www
source venv/bin/activate
gunicorn -w 4 -b 127.0.0.1:8000 vsearch4web:app

重新啓動gunicorn,若報錯,就殺進程,再次啓動,直到啓動成功。

然後斷開連接。再次連接,輸入

service nginx start

若不報錯,則服務啓動成功,使用公網IP:8000或域名:8000訪問你的flask項目吧。若報錯,或者是端口被佔用,查端口殺進程;或者是配置中的端口不適合,這時需要改端口,因爲並不是所有進程都能殺;或者是nginx已經運行,使用如下命令:

pkill -9 nginx

即可。

我的項目效果如下:

7、supervisor守護插件

我們先看一下,nginx是一個服務,這個服務不會莫名其妙被關閉。但是gunicorn是個進程,可能會因爲各種奇奇怪怪的原因而阻塞或者關閉。爲了保持gunicorn的運行,需要使用守護進程。如果沒有這個,那麼一旦斷開連接,gunicorn進程就會關閉,我們也就不能再用webapp了。

supervisor安裝如下:

pip install supervisor
echo_supervisord_conf > supervisor.conf
vim supervisor.conf

第一行是安裝supervisor,第二行是創建配置文件,第三行是修改配置。修改配置很重要,按如下形式修改:

[program:webapp]
command=/home/www/venv/bin/gunicorn -w 4 -b 127.0.0.1:8000 vsearch4web:app
directory=/home/www/webapp
startsecs=0
stopwaitsecs=0
autostart=true
autorestart=true
stdout_logfile=/home/www/webapp/gunicorn.log
stderr_logfile=/home/www/webapp/gunicorn.err

這個[program:webapp]中的webapp,指的是要守護的進程的名字,我們自己起一個,隨便叫什麼。

第二行就是要執行的操作,一旦進程沒了,通過這個操作重新啓動進程。這句就和之前啓動gunicorn的一樣。

第三行是我們的代碼所在的文件夾。

之後就是一些設置了。注意把兩個start都設置成true。

然後保存。輸入以下命令:

supervisord -c supervisor.conf

表示根據後面的配置啓動supervisor。這句代碼使用時,工作路徑應在配置文件所在的文件夾內。

然後輸入以下命令:

supervisorctl -c supervisor.conf

啓動supervisor控制檯。注意沒有-c supervisor.conf這部分的話,會報錯no route to host,我也不知道爲什麼,有就可以順利啓動。

然後輸入start webapp就可以啓動進程了。

如果配置文件有更新,使用如下命令:

supervisorstl -c supervisor.conf
update

即可。

整個響應流程就是:

客戶端訪問域名:端口,發出請求,nginx將請求轉發給gunicorn設置的本地端口,flask發現本地端口有訪問請求,調用python中的代碼。

8、後記

這部分可折騰死我了。

關閉gunicorn,如下:

首先執行如下命令獲取gunicorn進程樹:

pstree -ap|grep gunicorn

之後輸入如下指令關閉進程:

kill -9 pid

因爲gunicorn是一棵進程樹,所以如果按netstat -ntlp關閉進程的話會關不乾淨,要找到主進程的pid,直接關閉主進程才行。

關閉supervisor:

首先利用find / -name supervisor.sock找到supervisor的路徑,

然後輸入unlink 路徑關閉進程。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章