首先,本文的mysite是指自己的站點名稱。
安裝nginx
apt-get install nginx
關閉nginx默認的log
vi /etc/nginx/nginx.conf
找到以下access_log和error_log,修改為null。
access_log /dev/null;
error_log /dev/null;
接下來配置站點配置,進入nginx站點配置目錄,并新建配置文件
cd /etc/nginx/sites-available/
vi mysite
寫入一下對應站點配置文本,并保存
server {
listen 80;
server_name www.mysite.com mysite.com;
#修改最大上傳為10M,默認為2M,超出大小出現(xiàn)413 Request Entity Too Large錯誤
client_max_body_size 10M;
#一定要記得在網(wǎng)站目錄下創(chuàng)建logs文件夾,不然會報錯,不需要可注釋掉
#access_log /var/www/mysite/logs/access.log;
#error_log /var/www/mysite/logs/access.log;
#默認請求,nginx反向代理(動態(tài)頁面轉發(fā)至gunicorn)
location / {
#將訪客IP加入headers中,否則獲取到的將是127.0.0.1
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
#如果請求的文件不存在,則將路由轉發(fā)到gunicorn的8000端口
if (!-f $request_filename) {
proxy_pass http://127.0.0.1:8000;
break;
}
}
#靜態(tài)文件請求轉發(fā)給目錄
location ^~ /static/ {
root /var/www/mysite/app;
}
}
上面的內容中proxy_pass http://127.0.0.1:8000; 是表示動態(tài)頁面轉發(fā)到本機8000端口,這個端口就是gunicorn開放的服務。
這樣靜態(tài)頁面nginx就直接返回給訪客,動態(tài)頁面則轉發(fā)給gunicorn處理。
這里插一句:由于使用nginx反向代理到gunicorn,那么在flask中獲取IP就需要
//X-Forward-For參數(shù)為nginx反向代理轉發(fā)到gunicorn時設置的參數(shù)
ip = request.headers.get('X-Forward-For') or request.remote_addr
啟用站點配置文件
cd /etc/nginx/sites-enabled
#添加引用鏈接
ln -s /etc/nginx/sites-available/mysite ./mysite
#查看引用是否成功
ls -l
檢測配置文件是否有錯誤
sudo nginx -t
重啟nginx
service nginx restart
開啟防火墻端口
如果系統(tǒng)中沒有安裝ufw,則可以跳過,沒有安裝的話表現(xiàn)為命令不識別。
安裝了ufw的話,如果相關端口沒有開放,配置好nginx后會出現(xiàn)自己可以訪問(wget網(wǎng)址試試),外網(wǎng)卻無法訪問
#查看開放的端口
ufw status
#添加80端口
ufw allow 80
安裝Gunicorn
進入配置好的virtualenvs虛擬目錄,激活網(wǎng)站虛擬環(huán)境
cd /var/virtualenvs
source mysite_venv/bin/activate
安裝Gunicorn
pip install gunicorn
#進入網(wǎng)站根目錄
cd /var/www/mysite
#創(chuàng)建配置文件
vi gunicorn.conf
輸入配置文本并保存:
# 進程為5
workers = 5
# 監(jiān)聽本地8000端口,之后這個端口來的就是看這個網(wǎng)站的。
bind = '127.0.0.1:8000'
#如果要搭配gevent使用,請加上取消注釋
#worker_class="gevent" #sync, gevent,meinheld
注意:如果需要使用gevent模式,請先pip install gevent,然后在gunicorn.conf配置文件中加上worker_class="gevent",其他都和往常一樣。
gunicorn啟動測試
cd /var/www/mysite
gunicorn -c gunicorn.conf myapp:app
啟動后提示:
到這里gunicorn已經(jīng)安裝并配置好了,如果要正常用gunicorn啟動網(wǎng)站項目,需要項目中有對應的啟動文件,現(xiàn)在可以先跳過這一步,直接跳到安裝Supervisor。
當我們安裝并配置好 gunicorn 之后,需要用 gunicorn 啟動 flask,注意網(wǎng)站項目中 manage.py里面的 app.run(),這句代碼是作為 flask 自帶的server服務的啟動 入口,由于flask自帶的server很性能很差,這里我們服務器上使用 gunicorn,manage.py和myapp.py一樣,都是作為啟動入口文件,供server調用運行。在項目的manage.py文件中,gunicom不會執(zhí)行代碼中的.run(),是需要加上一段代碼對接gunicom。
在網(wǎng)站項目中需要一個gunicorn的啟動入口的文件,如果沒有就自己新建一個文件,名字無所謂,我取的是myapp.py,
內容為
import os
from app import create_app,db
app = create_app(os.getenv('mysite_CONFIG') or 'default')
#使用Gunicorn需要這兩行代碼對接
from werkzeug.contrib.fixers import ProxyFix
app.wsgi_app = ProxyFix(app.wsgi_app)
這個文件和manage.py一樣,也是一個啟動文件,不同的是,myapp.py專門作為gunicorn啟動使用,manage.py是用作flask自帶的web-server啟動,同時manage.py里面還有一些管理代碼,一樣可以使用python manage.py shell或python manage.py db init等命令來管理數(shù)據(jù)庫。
運行Gunicorn,
--config gunicorn.conf是根據(jù)配置文件來運行
manage為自己的run文件
gunicorn -c gunicorn.conf myapp:app
安裝Supervisor
我們的網(wǎng)站現(xiàn)在雖然能訪問了,但是假如你重啟服務器,網(wǎng)站的動態(tài)文件就會打不開,因為gunicorn不會開機自己啟動,需要一個小保姆開機后自動給他啟動,這里我們就使用supervisor。
Supervisor是一款服務器管理工具,用于監(jiān)控和守護進程。阿里云會偶爾宕機,宕機后會切換物理服務,造成服務器重啟。故而官網(wǎng)也強調過,程序最好有自動重啟、重連機制。所以我們需要Supervisor當保姆,照顧我們的后臺進程。
apt-get install supervisor
注意:supervisor需要系統(tǒng)默認是python2.7才能兼容支持,否則會安裝失敗,使用python -V查看系統(tǒng)默認py版本
向supervisor添加gunicorn的啟動項
cd /etc/supervisor/conf.d
vi mysite.conf
粘貼一下文本并保存
# 進程的名字,取一個以后自己一眼知道是什么的名字。(這行字不能刪,第一行需要一行注釋,刪了就有問題)
[program:mysite]
# 定義Gunicorn啟動命令,我們手動在ssh啟動Gunicorn需要cd到網(wǎng)站目錄然后輸入 gunicorn -c gunicorn.conf myapp:app,所以這里所有路徑都要寫成絕對路徑,這樣系統(tǒng)才能找到這些路徑
command=/var/virtualenvs/mysite_venv/bin/gunicorn myapp:app -c /var/www/mysite/gunicorn.conf
# 網(wǎng)站目錄
directory=/var/www/mysite
# 進程所屬用戶
user=root
# 自動重啟設置。
autostart=true
autorestart=true
# 日志存放位置(可能造成print中文UnicodeEncodeError)
#stdout_logfile=/var/www/mysite/logs/gunicorn_supervisor.log
# 設置環(huán)境變量。這里這行的意思是:設置環(huán)境變量MODE的值為UAT。請根據(jù)自己的需要配置,如沒有需要這行可以刪除。
#environment = MODE="UAT"
[supervisord]
保存后就進入supervisorctl控制臺
supervisorctl
進入控制臺
reread
update
start mysite
啟動完成后,以后每次開機supervisor都會幫我們自動按照配置文件啟動gunicorn服務。
如果發(fā)生錯誤請退出控制臺,嘗試重啟服務
service supervisor restart
現(xiàn)在重啟服務器后,如果網(wǎng)站能正常訪問了,說明gunicorn自動啟動了,這也表示我們的supervisor配置成功了。
以后如果更新了網(wǎng)站項目文件,讓gunicorn重新加載新的項目文件也只需要使用supervisor管理gunicorn進程就好了。
重新載入配置文件并停止所有進程并按新的配置啟動:supervisorctl reload
以下是所有supervisorctl 的命令
supervisorctl status: 查看當前運行的進程列表
supervisorctl stop xxx: 停止某一個進程(xxx),xxx為[program:theprogramname]里配置的值。
supervisorctl start xxx: 啟動某個進程
supervisorctl restart xxx: 重啟某個進程
supervisorctl stop groupworker: 重啟所有屬于名為groupworker這個分組的進程(start,restart同理)
supervisorctl stop all,停止全部進程,注:start、restart、stop都不會載入最新的配置文件。
supervisorctl reload,載入最新的配置文件,停止原有進程并按新的配置啟動、管理所有進程。
supervisorctl update,根據(jù)最新的配置文件,啟動新配置或有改動的進程,配置沒有改動的進程不會受影響而重啟。
注意:顯示用stop停止掉的進程,用reload或者update都不會自動重啟。
supervisor使用中遇到的一些錯誤
============錯誤A
參考https://www.v2ex.com/t/210122
如果提示unix:///var/run/supervisor.sock no such file
error: <class 'socket.error'>, [Errno 2] No such file or directory: file: /usr/lib/python2.7/socket.py line: 224
這表明supervisord服務端沒有成功啟動,多半是/etc/supervisor/conf.d下面自己的配置文件出問題
cd /etc/supervisor/conf.d
supervisord -c mysite.conf
這里就告訴我配置文件17行出了問題
修改好配置文件后,
#重新生成supervisor.sock文件,啟動監(jiān)聽服務
supervisord -c supervisord.conf
#重新加載自定義配置文件
supervisorctl reload
============錯誤B
如果配置文件有錯誤,會提示你提示
如果有錯誤則exit退出控制臺,vi mysite.conf修改錯誤后再繼續(xù)進入控制臺,并reread重新讀取配置文件。
如果都正確了,則在supervisorctl的控制臺中輸入命令,啟動supervisor任務。
(注意:如果要supervisor啟動任務,則會啟動gunicorn,自己先使用gunicorn命令試試能否正常啟動網(wǎng)站項目)。
#進入網(wǎng)站目錄
cd /var/www/mysite
#測試能否正常啟動網(wǎng)站項目
gunicorn -c gunicorn.conf myapp:app
如果能正常啟動就ctrl+c結束,然后繼續(xù)進入supervisorctl啟動任務。
supervisorctl
==============錯誤C
這樣就錯誤:
[program:taokeapi]
# 定義Gunicorn啟動命令,我們手動在ssh啟動Gunicorn需要cd到網(wǎng)站目錄然后輸入 gunicorn -c gunicorn.conf myapp:app,所以>這里所有路徑都要寫成絕對路徑,這樣系統(tǒng)才能找到這些路徑
command=/var/virtualenvs/taokeapi_venv/bin/gunicorn myapp:app -c /var/www/taokeapi/gunicorn.conf
# 網(wǎng)站目錄
directory=/var/www/taokeapi
# 進程所屬用戶
user=root
# 自動重啟設置。
autostart=true
autorestart=true
[supervisord]
這樣就正確:
# 進程的名字,取一個以后自己一眼知道是什么的名字。
[program:taokeapi]
# 定義Gunicorn啟動命令,我們手動在ssh啟動Gunicorn需要cd到網(wǎng)站目錄然后輸入 gunicorn -c gunicorn.conf myapp:app,所以>這里所有路徑都要寫成絕對路徑,這樣系統(tǒng)才能找到這些路徑
command=/var/virtualenvs/taokeapi_venv/bin/gunicorn myapp:app -c /var/www/taokeapi/gunicorn.conf
# 網(wǎng)站目錄
directory=/var/www/taokeapi
# 進程所屬用戶
user=root
# 自動重啟設置。
autostart=true
autorestart=true
[supervisord]
差別僅僅是第一行多了一行注釋。。。
不知道是BUG還是什么,總之第一行需要注釋,去掉就會出問題。。。
======錯誤D
使用supervisor啟動gunicorn,執(zhí)行print就出錯。
而直接啟動gunicorn則沒問題。
可見錯誤在supervisor上面。。
經(jīng)過多次排查,發(fā)現(xiàn),
vi /etc/supervisor/conf.d/taokeapi.conf配置文件中多了一行,
stdout_logfile=/var/www/mysite/logs/gunicorn_supervisor.log
由于supervisor是基于python2,當運行python3的項目時,print就會被寫入這個日志文件,python2在有些系統(tǒng)中輸出中文就會出現(xiàn)UnicodeEncodeError錯誤。
解決辦法:
配置文件中去掉這行輸出日志目錄,完整配置如下:
# 進程的名字,取一個以后自己一眼知道是什么的名字。
[program:taokeapi]
# 定義Gunicorn啟動命令,我們手動在ssh啟動Gunicorn需要cd到網(wǎng)站目錄然后輸入 gunicorn -c gunicorn.conf myapp:app,所以>這里所有路徑都要寫成絕對路徑,這樣系統(tǒng)才能找到這些路徑
command=/var/virtualenvs/taokeapi_venv/bin/gunicorn myapp:app -c /var/www/taokeapi/gunicorn.conf
# 網(wǎng)站目錄
directory=/var/www/taokeapi
# 進程所屬用戶
user=root
# 自動重啟設置。
autostart=true
autorestart=true
[supervisord]
然后重新加載配置文件
supervisord -c taokeapi.conf
supervisorctl
>reread
>update
>reload
這樣就發(fā)現(xiàn)沒問題了