Fancy‘s Blog

Fancy's Blog,技術Blog在SC語言
tc sc en

uWSGI和Gunicorn對比實踐筆記

2019-01-27 Code Fancy

从flask微信公众号后台分析Ubuntu+Python3+pipenv+flask环境下 uWSGI/Gunicorn+supervisor+nginx配置问题

在服務器能正常通信後,Werkzeug提供的的WSGI並不適合生產環境,調試完代碼第一件事就找個獨立WSGI容器。我們這裏選擇uWSGI和gunicorn,相對來說這兩個比gevent更適合大型項目,uWSGI出現的比較早,gunicorn是從Ruby的unicorn移植而來,配置也簡單。為了熟悉uwsgi我都嘗試一下吧

這裏的示例程序代碼接上篇使用Flask創建微信公眾號

uWSGI配置

這裏我們先配置uwsgi,或者使用gunicorn,這兩個任選其一。 如果是新浪SAE的話記得刪除app.run()裏的port,並且以下所有端口都是5050。

$ pipenv install uwsgi

然後運行

$ uwsgi --socket 0.0.0.0:5000 -w main:app

可以加上–protocol=http以指定協議,我們的項目啟動文件名為main.py對應修改即可,運行http://server_domain_or_IP:5000倘若能看到我們在視圖函數寫的Hello World!即可。 如果開了防火墻莫忘了開啟端口,以Ubuntu的ufw為例:

$ sudo ufw allow 5000

到此,可以到項目根目錄創建配置文件wepub_uwsgi.ini,這裏名字隨意。

wepub_uwsgi.ini:

[uwsgi]
module = main:app
#用以啟動程序名
master = true
processes = 4
#子進程數量
chdir = /root/WePub/wepub
#python啟動程序目錄
socket = /root/WePub/wepub/wepub_uwsgi.sock
#uwsgi 啟動後所需要創建的文件,和 Nginx 通信,配置 Nginx 時用
logto = /root/WePub/wepub/%n.log
chmod-socket = 660
#賦予 .sock 文件權限與 Nginx 通信
vacuum = true
http = 0.0.0.0:5050
#http地址和端口

保存後運行:

$ uwsgi --ini wepub_uwsgi.ini

此時運行時會在設置的目錄生成與配置文件同名的.sock文件,先不要關閉,等配置好Nginx後方可關閉確認後跳過gunicorn章節,即配置Nginx。

gunicorn配置

個人偏好於gunicorn,用的比較多了,至於區別,gunicorn比較好部署理解,性能上的短板還在我身上,安裝gunicorn

$ pipenv install gunicorn

運行

$ gunicorn -w 4 -b 0.0.0.0:8000 main:app

其中-w 是–workers是定義同步worker的數量,–bind為主機地址和端口,不用異步的話這就夠了 gunicorn的配置文件還能實現復雜的配置,目前學有不精,先不做討論

uWSGI配置nginx

nginx反向代理使用比較多了,流程都比較一致,這裏就簡潔帶過吧

$ sudo apt install nginx

這裏我們先把nginx的配置文件找個位置備份好

$ mv /etc/nginx/sites-enabled/default ~/nginx.backup

而後直接定義server塊,listen監聽80端口 (新浪SAE為5050端口)

$ vi /etc/nginx/sites-enabled/wepub

wepub:

server {
    listen  80;
    server_name _;

    location / {
    include      uwsgi_params;
    uwsgi_pass unix:/root/WePub/wepub/wepub_uwsgi.sock;
    }
}

server_name可以指定HOST域名解析後的公網地址,這裏默認用的是通配符 這裏是最簡配置,定義日誌存放重寫請求頭部這些,有機會再詳細說明吧 如果項目有靜態文件的話,設置路徑與過期時間

location /static {
    alias /the/path/to/staitic;
    expires 30d;
}

保存退出,最後 sudo nginx -t 檢查語法錯誤,期待返回

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

有錯誤的話檢查一下,而後重啟nginx使配置生效

$ sudo service nginx restart

gunicorn配置nginx

只是配置文件不同

wepub:

server {
    listen 80;
    server_name example.org;


    location / {
    proxy_pass http://127.0.0.1:8000; #轉發gunicorn運行地址
    }
 }

location 只需要直接轉發gunicorn運行地址即可運行,這裏是最簡配置,成功後直接80地址即可訪問服務器反向代理部分:

    location / {
        proxy_pass         http://localhost:8000/; #gunicorn 運行地址
        proxy_redirect     off;

        proxy_set_header   Host             $http_host;
        proxy_set_header   X-Real-IP        $remote_addr;
        proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
    }

管理uWSGI進程:

這裏的差別主要就各自的命令而已,就放在一起說吧 對於uWSGI來說,uWSGI服務與nginx通信時依賴於sock文件,網站運行時無法關閉,始終不可靠,這裏我們利用Supervisor管理並監控uWSGI的進程,

$ sudo apt install supervisor

這裏我們不更改全局配置,為我們的程序單獨創建配置文件

$ sudo vi /etc/supervisor/conf.d/wepub.conf

wepub.conf:

[program:wepub]
command = pipenv run uwsgi /root/WePub/wepub/wepub_uwsgi.ini ;監控uWSGI
# command=pipenv run gunicorn -w 4 main:app       監控Gunicorn
directory=/root/WePub/wepub                    ;程序目錄
user=root                    ; 程序啟動用戶,最好不要用root
autostart=true                 ; 隨supervisor啟動而啟動
autorestart=true              ; 自動重啟
stopasgroup=true           ; 關閉程序時關閉子進程
killasgroup=true             ; 殺死程序時殺死子進程
stderr_logfile=/root/WePub/wepub/err.log   ;錯誤日誌文件
stdout_logfile=/root/WePub/wepub/out.log  ;程序日誌文件
stopsignal=INT          ; 殺死進程的自定信號
startretries=10               ; 啟動失敗時的重試次數

[supervisord]

我們:wq保存後檢查配置文件是否正確:

$ supervisord -c /path/to/my/config.conf

返回的錯誤信息挺詳細的,根據問題修改即可。確認無返回的時候重啟supervisor

$ sudo service supervisor restart

如果運行過程中出現錯誤,可以查看supervisor的錯誤日誌。也可以在supervisorctl命令行中進行查看與操作程序,也可以開啟9001瀏覽器訪問。


瀏覽器輸入Nginx顯示502badway,一般這時候是防火墻沒打開或者sock文件位置有誤

提示unix:///var/run/supervisor.sock no such file除了supervisor安裝問題之外, 一般來說是指定位置或者和權限的問題

[unix_http_server]
file=/var/run/supervisor.sock   ; (socket 文件位置)
chmod=0700                       ; sockef file mode (default 0700)

如果是提示編碼出錯還需解決pipenv的編碼問題

$ sudo vi /etc/supervisor/supervisord.conf

在[supervisord]的最後添加環境設置:

environment=LC_ALL='zh_CN.UTF-8', LANG='zh_CN.UTF-8'
  • 不知道新浪SAE怎麽搞得非要debian系限定的C.UTF-8,我想這並不是個好辦法

img

environment=LC_ALL='C.UTF-8', LANG='C.UTF-8'

至此應該能得到一個還算穩定安全的部署程序了,應該足以應對個人微信公眾號這些並發不高無需協程的了。 關於每個部分的詳細設置都有很多,還是詳細閱讀文檔吧。這裏如果遇到什麽問題的話還請指教

comments powered by Disqus