使用Nginx+Gunicorn+systemd部署flask應用

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服務

  1. 假設我們在/opt/sampleapp下面有一個文件執行文件,使用gunicorn的啓動方式就是gunicorn sample:app -b 0.0.0.0:8000
  2. 需要在/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
    
  3. 然後我們需要設置權限並且使改變生效:
    chmod 755 /etc/systemd/system/sampleapp.service
    systemctl daemon-reload
    
  4. 然後用下面命令來操作:
    # 啓動
    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服務器,有負載均衡,攔截靜態請求,高併發等功能:

  1. 它可以僅通過前端的唯一URL訪問分發到後臺的多個服務器上,通常會監聽80端口
  2. 它可以攔截靜態請求,比如靜態文件或者圖片,並交給Nginx本身來處理。動態的請求內容則通過WSGI容器(Gunicorn)交給web應用處理
  • 所以這樣的話,有兩種架構方式:
  1. web應用+WSGI容器+Nginx:WSGI容器比如Gunicorn是一箇中間件
  2. web應用+WSGI容器:WSGI容器就是web服務器
  • 實際部署方案:
    讓Nginx綁定80端口,接受客戶端的請求,靜態資源請求自己處理,但是將動態內容請求反向代理給運行在本地端口的WSGI容器。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章