使用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容器。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章