網上找了許多講關於Flask應用部署的文章幾乎都是一個helloworld的Demo,按照helloworld來部署都沒問題,但實際項目部署時還是遇到了不少問題。在這里簡單寫下自己成功部署的過程,防止下次部署時就忘記了,好記性不如爛筆頭這句話不是蓋的。
部署環境:
OS: Ubuntu 14.04.4 LTS
Python: 2.7.6
Nginx: nginx/1.4.6(Ubuntu)
uwsgi: 1.9.17.1-debian
supervisord: 3.0b2
這個署架構中Nginx主要作為前置服務器,負責分發處理來自客戶端的請求,uwsgi作為后端Flask應用的容器,supervisor作為監控程序,即看門狗。
由於項目源碼是直接放在阿里雲服務器上(項目已開源http://github.com/yelongyu/chihu.git),所以這里省略了項目上傳這一步,並假設已經安裝好了Python開發環境,若未配置好Python開發環境,請先配置好,本文假設項目所在的位置為/home/chihu。
環境配置:
sudo apt-get install uwsgi-plugin-python # 這個不裝的話當發起請求時uwsgi會報錯
若是Python3的話改為:
sudo apt-get install uwsgi-plugin-python3
STEP 1: Nginx安裝配置
安裝Nginx
1. 輸入Nginx安裝命令
sudo apt-get install nginx
2. 啟動Nginx服務器:
sudo service nginx start
啟動Nginx服務器並用瀏覽器訪問測試一下Nginx是否安裝成功,若成功,進入下一步。
3. 配置Nginx
進入/etc/nginx/sites-enabled/文件夾 注意不是sites-available
直接配置
/etc/nginx/nginx.conf也可以,不過要根據其語法來配置,其實最后nginx.conf還是會調用/etc/nginx/sites-enabled/default的配置。
- 先將默認配置文件default備份(養成修改配置前先備份的習慣):
mv default default.bak
- 編輯配置文件:
vim default
- 寫入配置內容:
server {
listen 80; # 服務器監聽端口
server_name 110.110.110.110; # 這里寫你的域名或者公網IP
charset utf-8; # 編碼
client_max_body_size 75M; # 之前寫的關於GET和POST的區別,這里應該是原因之一吧
location / {
include uwsgi_params; # 導入uwsgi配置
uwsgi_pass 127.0.0.1:8000; # 轉發端口,需要和uwsgi配置當中的監聽端口一致
uwsgi_param UWSGI_PYTHON /home/chihu/venv; # Python解釋器所在的路徑(這里為虛擬環境)
uwsgi_param UWSGI_CHDIR /home/chihu; # 項目根目錄
uwsgi_param UWSGI_SCRIPT manage:app; # 項目的主程序,即Flask app所在的位置
}
}
輸入:wq保存配置文件。配置好了之后別急着啟動Nginx,記得先通過nginx -t測試一下配置文件是否正確,若檢測配置文件失敗,再好好檢查下配置文件有沒有疏漏。
此時訪問Nginx服務器應該會得到502 Bad Gateway的提示,因為請求被Nginx轉發了,但是並沒有轉發服務器來處理請求(還沒有配置好uwsgi)。
STEP 2: uwsgi安裝配置
安裝uwsgi
sudo apt-get install uwsgi
編寫uwsgi配置文件
在項目文件根目錄新建配置文件uwsgi.ini(uwsgi支持多種配置文件格式: xml, ini, json等)
vim uwsgi.ini
寫入配置內容如下:
[uwsgi]
socket = 127.0.0.1:8000 # uwsgi的監聽端口
plugins = python # 這行一定要加上,不然請求時會出現-- unavailable modifier requested: 0 --錯誤提示
chidir = /home/chihu # 項目根目錄
wsgi-file = manage.py # flask程序的啟動文件
callable = app # 程序變量名
輸入:wq保存配置文件,可以通過uwsgi uwsgi.ini來啟動uwsgi。
STEP 3: 啟動及測試
Nginx和uwsgi都配置好了之后下一步就是啟動Nginx和uwsgi了。
- 啟動Nginx
sudo service nginx restart
- 啟動uwsgi
進入項目根目錄,即uwsgi.ini所在的目錄,執行以下命令。
uwsgi wsgi.ini
若一切正常的話就可以在終端上看到uwsgi的啟動信息了。
測試:
打開瀏覽器訪問服務器,若可以正常訪問,說明Nginx和uwsgi配置成功了,但離真正項目上線還差一段,因為uwsgi是直接在前台啟動的,當我們的連接終端跟服務器斷開的時候uwsgi進程也被關閉了,所以我們需要讓uwsgi在后台運行。
STEP 4: 進程監控
原本打算用uwsgi emperor的方式運行uwsgi即讓uwsgi成為守護進程(daemon),但是折騰了一天還是沒解決問題,遂換supervisor。(折騰uwsgi emperor到后面發現問題是,當單獨使用uwsgi的時候一切正常,但一使用uwsgi emperor就會出現os.environ.get()獲取不到環境變量的問題,但環境變量明明可以通過env看到,直接在Python終端上執行os.environ.get()也可以獲取到.....等有時間再回過頭了折騰。)
單獨一個uwsgi程序運行短時間可能沒問題,但是網絡狀況瞬息萬變,萬一uwsgi進程掛了網站也就訪問不了了.....為了防止出現意外情況,還需要一個監控程序來監控uwsgi的狀況,這里該supervisor出場了。具體什么是supervisor可以Google之。
1. 首先安裝supervisor
sudo apt-get install supervisor
2. 生成默認配置文件
echo_supervisord_config > supervisord.conf
3. 加入監控程序的配置
[program:project_name] # project_name這里寫上你的項目名稱,如我的為[project:chihu]
command = uwsgi --ini /home/chihu/uwsgi.ini # 跟手動啟動的命令一樣
stopsignal=QUIT
autostart=true
autorestart=true
stdout_logfile=/var/log/uwsgi/supervisor_chihu.log # 運行日志
stderr_logfile=/var/log/uwsgi/supervisor_chihu_err.log # 錯誤日志
4. 啟動supervisord
supervisorctl reload
5. 檢查uwsgi進程是否正常運行
ps aux|grep uwsgi
如果一切正常,此時應該可以看到uwsgi進程
嘗試kill掉uwsgi進程看supervisor會不會重新啟動一個新的uwsgi進程
sudo killall uwsgi
若再次通過ps aux|grep uwsgi查看發現有新的uwsgi進程在運行,那差不多可以祝你成功了, God bless you。
ERROR
supervisorctl reload
提示錯誤
error: <class 'socket.error'>, [Errno 2] No such file or directory: file: /usr/lib/python2.7/socket.py line: 224
issue
只需手動啟動supervisord即可:
sudo supervisord -c configfile.conf
這里涉及到一個啟動程序的用戶的問題,好幾次莫名不能通過os.environ.get()到系統中的環境變量,導致程序出錯。一步一步排查猜測是因為啟動程序的用戶不匹配的問題,遂將啟動程序的用戶從root改為普通的登陸用戶,問題解決,但這里還有疑問,因為環境變量是設置在/et/environment當中的,按理這里設置的應該是全局都可以訪問的環境變量,但是當用root用戶啟動程序時就不能訪問到環境變量,為了這個問題折騰了好幾天,總算解決了,但是當中的疑惑還是需要好好思考探索。
后記:
折騰了兩天終於搞定,有時候教程看着簡單,你的配置也和教程一樣,但就是由於各種錯誤無法運行,雖然說計算機非0即1,是我們人類最忠實可靠的伙伴,但是有時候就差那么一點點,有可能是軟件環境不對亦或是我們電腦的打開方式不對...總之,就是要有那么個折騰的過程,所謂吃一塹長一智,不折騰折騰估計過后就忘了怎么回事了,還是要勤動手不放棄,雖然被一個uwsgi emperor折騰得快要懷疑人生了,但我還是堅定不移地...改道supervisor了 :)
初次寫教程,文中可能有疏漏或寫得不夠恰當的地方,還請各位看官多多包涵,歡迎指正和交流。如果部署的過程中有問題也歡迎留言,雖然不能保證可以解決。
-EOF-
參考:
https://segmentfault.com/a/1190000004294634 # uwsgi及Nginx配置
http://vladikk.com/2013/09/12/serving-flask-with-nginx-on-ubuntu/#comment-2401229330 # uwsgi emperor
http://letgoof.me/2013/deploy-django-project-with-uwsgi-nginx-and-supervisor/ # supervisor配置
http://liyangliang.me/posts/2015/06/using-supervisor/ # supervisor & supervisord
