Flask,Django自帶的web server目的就是用於開發,而不是生產環境,自帶的server應該只能開單進程,而gunicorn和wsgi是專門爲生產環境開發的,能配置更多從而處理更加複雜的請求狀態,性能和穩定性都更好。
使用gunicorn啓動flask應用:
pip install gunicorn
gunicorn app:app -b localhost:8000 &
第一個app是模塊文件的名字,即在這個文件中創建了flask app,第二個app是文件中創建的flask實例的名字,所以如果文件wsgi.py像下面這樣:
from app import create_app
app = create_app()
啓動應用的命令就應該是:
gunicorn wsgi:app -b localhost:8000 &
gunicorn -w 3 wsgi:app -b localhost:8000 & # 啓動了三個進程
退出,關閉,重啓gunicorn進程:
獲取gunicorn進程樹:pstree -ap|grep gunicorn
重啓gunicorn任務:kill -HUP 14226
(第二層pid)
退出gunicorn任務:kill -9 28097
(第一層pid)
使用systemd來管理gunicorn服務
- 假設我們在
/opt/sampleapp
下面有一個文件執行文件,使用gunicorn的啓動方式就是gunicorn sample:app -b 0.0.0.0:8000
- 需要在
/etc/systemd/system/
下面創建一個名字爲sampleapp.service
的文件,文件內容:[Unit] Description = SampleApp # 描述 After = network.target [Service] PermissionsStartOnly = true PIDFile = /run/sampleapp/sampleapp.pid User = sampleapp Group = sampleapp WorkingDirectory = /opt/sampleapp # 執行文件的路徑 ExecStartPre = /bin/mkdir /run/sampleapp ExecStartPre = /bin/chown -R sampleapp:sampleapp /run/sampleapp ExecStart = /usr/bin/env gunicorn sample:app -b 0.0.0.0:8000 --pid /run/sampleapp/sampleapp.pid ExecReload = /bin/kill -s HUP $MAINPID ExecStop = /bin/kill -s TERM $MAINPID ExecStopPost = /bin/rm -rf /run/sampleapp PrivateTmp = true [Install] WantedBy = multi-user.target
- 然後我們需要設置權限並且使改變生效:
chmod 755 /etc/systemd/system/sampleapp.service systemctl daemon-reload
- 然後用下面命令來操作:
# 啓動 systemctl start sampleapp.service # 查看狀態 systemctl status sampleapp.service # 停止服務 systemctl stop sampleapp.service # 重啓服務 systemctl restart sampleapp.service
這裏使用一個例子:
比如我們的環境其實是在虛擬環境當中,然後使用systemd來啓動gunicorn
[Unit]
Description = project
After = network.target
[Service]
WorkingDirectory = /home/user/project/project_C
ExecStart = /home/user/.local/share/virtualenvs/CUS-C-EiCxwBq2/bin/gunicorn wsgi:wsgi -b 0.0.0.0:8080
Type = simple
[Install]
WantedBy = multi-user.target
這裏的WorkingDirectory其實就是指定了執行命令的路徑
然後我們使用gunicorn的配置文件來配置gunicorn
# -*- coding: utf-8 -*-
# gunicorn.py
import multiprocessing
bind = '0.0.0.0:8080'
timeout = 120
worker_class = 'gevent'
workers = multiprocessing.cpu_count() + 1 # 進程數
threads = 2 # 每個進程開啓的線程數量
accesslog = "/home/wangyf/CUS/CUS-C/gunicorn_access.log"
errorlog = "/home/wangyf/CUS/CUS-C/gunicorn_error.log"
在service文件裏面就應該修改成
ExecStart = /home/user/.local/share/virtualenvs/CUS-C-EiCxwBq2/bin/gunicorn
-c gunicorn.py wsgi:wsgi
web服務器,web應用,WSGI 之間的聯繫:
-
WSGI翻譯爲python web服務器網關接口–>python的應用(Flask)和web服務器(比如Nginx)之間的通信協議,所以如果想讓應用在web服務器上運行就必須遵守這個WSGI協議
-
實現WSGI協議的web服務器有uWSGI和Gunicorn,所以很多地方都是使用Nginx+Gunicorn的部署方式,但是實際上直接使用Gunicorn直接部署也是可以外網訪問的,那麼爲何要使用Nginx?
-
Nginx是一個高性能web服務器,有負載均衡,攔截靜態請求,高併發等功能:
- 它可以僅通過前端的唯一URL訪問分發到後臺的多個服務器上,通常會監聽80端口
- 它可以攔截靜態請求,比如靜態文件或者圖片,並交給Nginx本身來處理。動態的請求內容則通過WSGI容器(Gunicorn)交給web應用處理
- 所以這樣的話,有兩種架構方式:
- web應用+WSGI容器+Nginx:WSGI容器比如Gunicorn是一箇中間件
- web應用+WSGI容器:WSGI容器就是web服務器
- 實際部署方案:
讓Nginx綁定80端口,接受客戶端的請求,靜態資源請求自己處理,但是將動態內容請求反向代理給運行在本地端口的WSGI容器。