[1269]使用gunicorn部署flask项目

1、简介

flask 自带的web服务器可用于开发环境运行调试,不适合部署在生产环境,无法满足线上的性能要求。当使用app.run(host = '0.0.0.0',port=6000)启动时,flask框架会有一段 WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.

先介绍下几个概念,方便理解使用 wsgi server 部署的意义:

  • WSGI: 全称是Web Server Gateway Interface(web服务器网关接口),它是一种规范,它是web服务器和web应用程序之间的接口。它的作用就像是桥梁,连接在web服务器和web应用框架之间。
  • uwsgi: 是一种传输协议,用于定义传输信息的类型。
  • uWSGI: 是实现了uwsgi协议WSGI的web服务器。

gunicorn是一个python WSGI http server,我们这里采用它做 wsgi 服务器,来部署flask程序。

2、模块安装

pip install gunicorn

一般使用它,主要是为使用其异步的worker模型,还需要安装对应的异步模块。

pip install greenlet # 使用异步必须安装
pip install eventlet # 使用eventlet workers
pip install gevent   # 使用gevent workers

3、启动命令

3.1 命令行配置 gunicorn 参数

gunicorn 命令启动程序比较简单。以下面 main.py 为例

from flask import Flask

app = Flask(__name__)

@app.route('/',methods=['GET'])
def hello_world():
    return 'Hello World!'

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=6000)

运行命令:

gunicorn -w 5 -b 0.0.0.0:6000 -t 120 main:app

持久化运行,使用nohup,运行日志将存储于当前目录的app.log日志

nohup python -m gunicorn -w 5 -b 0.0.0.0:6000 -t 120 main:app > app.log 2>&1 &

解释下参数含义:

  • -w:表示工作进程数
  • -b :访问地址和端口
  • -t:设置超时时间120秒,默认30秒
  • main :flask启动python文件名
  • app  :脚本中创建的Flask对象名

注意:1、windows系统会报错:ModuleNotFoundError: No module named 'fcntl',原因是 gunicorn 不支持windows,在 linux 上可正常运行。

2、若遇到flask启动后,访问请求很慢,一般是 gunicorn 和 flask-socketio 版本不兼容,找到对应版本即可,我安装的都是最新版,没有问题。

如果生产环境,必不可少还需要配置日志信息,如下:

gunicorn -w 4 -b 0.0.0.0:8080 --access-logfile access.log --error-logfile error.log app:app -D

-D表示将gunicorn置于后台运行,可以通过tail -f access.log或者tail -f error.log查看记录的日志信息。

3.2 一些其他的Gunicorn命令示例

  • 运行一个名为myapp.py的Flask应用程序,启用访问日志和错误日志:
gunicorn --access-logfile access.log --error-logfile error.log myapp:app
  • 运行一个名为myapp.py的Flask应用程序,以守护进程模式运行:
gunicorn -D myapp:app
  • 运行一个名为myapp.py的Flask应用程序,指定配置文件:
gunicorn -c gunicorn.conf.py myapp:app
  • 重新加载正在运行的Gunicorn实例(平滑重启):
kill -HUP <主进程ID>
  • 停止正在运行的Gunicorn实例(优雅停止):
kill -TERM <主进程ID>
  • 运行一个名为myapp.py的Flask应用程序,设置工作进程的最大请求数:
gunicorn --max-requests 1000 myapp:app
  • 运行一个名为myapp.py的Flask应用程序,设置工作进程的最大请求数波动范围:
gunicorn --max-requests-jitter 50 myapp:app
  • 运行一个名为myapp.py的Flask应用程序,设置工作进程的名称前缀:
gunicorn --worker-tmp-dir /dev/shm myapp:app
  • 运行一个名为myapp.py的Flask应用程序,设置工作进程的临时目录:
gunicorn --worker-tmp-dir /dev/shm myapp:app
  • 运行一个名为myapp.py的Flask应用程序,启用SSL支持:
gunicorn --certfile=server.crt --keyfile=server.key myapp:app
  • 运行一个名为myapp.py的Flask应用程序,设置日志记录级别:
gunicorn --log-level debug myapp:app
  • 运行一个名为myapp.py的Flask应用程序,启用代理协议支持:
gunicorn --proxy-protocol myapp:app
  • 运行一个名为myapp.py的Flask应用程序,设置请求头大小限制:
gunicorn --limit-request-line 8190 myapp:app
  • 运行一个名为myapp.py的Flask应用程序,设置请求字段数量限制:
gunicorn --limit-request-fields 100 myapp:app
  • 运行一个名为myapp.py的Flask应用程序,设置请求字段大小限制:
gunicorn --limit-request-field_size 8190 myapp:app

请注意,上面的命令中的myapp:app表示您的应用程序位于名为myapp.py的文件中,并且Flask应用程序实例的名称为app。您需要根据您自己的应用程序进行相应修改。

3.3 文件配置 gunicorn 参数

3.3.1进程+线程模式

根目录新建配置文件 config.py

# 是否开启debug模式
debug = True
# 访问地址
bind = "0.0.0.0:6000"
# 工作进程数
workers = 2
# 工作线程数
threads = 2
# 超时时间
timeout = 600
# 输出日志级别
loglevel = 'debug'
# 存放日志路径
pidfile = "log/gunicorn.pid"
# 存放日志路径
accesslog = "log/access.log"
# 存放日志路径
errorlog = "log/debug.log"
# gunicorn + apscheduler场景下,解决多worker运行定时任务重复执行的问题
preload_app = True

运行命令:

gunicorn -c config.py main:app

看到以下信息表示启动成功

配置文件参数详解:

-c CONFIG    : CONFIG,配置文件的路径,通过配置文件启动;生产环境使用;

-b ADDRESS   : ADDRESS,ip加端口,绑定运行的主机;

-w INT, --workers INT:用于处理工作进程的数量,为正整数,默认为1;

-k STRTING, --worker-class STRTING:要使用的工作模式,默认为sync异步,可以下载eventlet和gevent并指定

--threads INT:处理请求的工作线程数,使用指定数量的线程运行每个worker。为正整数,默认为1。

--worker-connections INT:最大客户端并发数量,默认情况下这个值为1000。

--backlog int:未决连接的最大数量,即等待服务的客户的数量。默认2048个,一般不修改;

-p FILE, --pid FILE:设置pid文件的文件名,如果不设置将不会创建pid文件

--access-logfile FILE   :  要写入的访问日志目录

--access-logformat STRING:要写入的访问日志格式

--error-logfile FILE, --log-file FILE  :  要写入错误日志的文件目录。

--log-level LEVEL   :   错误日志输出等级。

--limit-request-line INT   :  HTTP请求头的行数的最大大小,此参数用于限制HTTP请求行的允许大小,默认情况下,这个值为4094。值是0~8190的数字。

--limit-request-fields INT   :  限制HTTP请求中请求头字段的数量。此字段用于限制请求头字段的数量以防止DDOS攻击,默认情况下,这个值为100,这个值不能超过32768

--limit-request-field-size INT  :  限制HTTP请求中请求头的大小,默认情况下这个值为8190字节。值是一个整数或者0,当该值为0时,表示将对请求头大小不做限制

-t INT, --timeout INT:超过这么多秒后工作将被杀掉,并重新启动。一般设定为30秒;

--daemon: 是否以守护进程启动,默认false;

--chdir: 在加载应用程序之前切换目录;

--graceful-timeout INT:默认情况下,这个值为30,在超时(从接收到重启信号开始)之后仍然活着的工作将被强行杀死;一般使用默认;

--keep-alive INT:在keep-alive连接上等待请求的秒数,默认情况下值为2。一般设定在1~5秒之间。

--reload:默认为False。此设置用于开发,每当应用程序发生更改时,都会导致工作重新启动。

--spew:打印服务器执行过的每一条语句,默认False。此选择为原子性的,即要么全部打印,要么全部不打印;

--check-config   :显示现在的配置,默认值为False,即显示。

-e ENV, --env ENV: 设置环境变量;
3.3.2进程+协程模式

根目录新建配置文件 config.py

from gevent import monkey
monkey.patch_all()

# 是否开启debug模式
debug = True
# 访问地址
bind = "0.0.0.0:6000"
# 工作进程数
workers = 2
# 设置协程模式
worker_class="gevent"  
# 最大客户端并发数量,默认情况下这个值为1000。此设置将影响gevent和eventlet工作模式
worker_connections=500
# 超时时间
timeout = 600
# 输出日志级别
loglevel = 'debug'
# 存放日志路径
pidfile = "log/gunicorn.pid"
# 存放日志路径
accesslog = "log/access.log"
# 存放日志路径
errorlog = "log/debug.log"
# gunicorn + apscheduler场景下,解决多worker运行定时任务重复执行的问题
preload_app = True

运行命令:

gunicorn -c config.py main:app

看到 using worker :gevent 模式启动

使用 gunicorn 部署到 docker 容器也比较方便,只要将启动命令写到 dockerfile 里即可。

其它可配置项:config.py

import logging
import logging.handlers
import os
import multiprocessing
import gevent.monkey
gevent.monkey.patch_all()

bind = '0.0.0.0:8080'  # 绑定的ip已经端口号
chdir = '/home/flaskProject'  # gunicorn要切换到的目的工作目录
timeout = 60  # 超时
worker_class = 'gevent'  # 使用gevent模式,还可以使用sync 模式,默认的是sync模式
workers = multiprocessing.cpu_count() * 2 + 1  # 启动的进程数
loglevel = "info"  # 日志级别,这个日志级别指的是错误日志的级别,而访问日志的级别无法设置
access_log_format = '%(t)s %(p)s %(h)s "%(r)s" %(s)s %(L)s %(b)s %(f)s" "%(a)s"'  # 设置gunicorn访问日志格式,错误日志无法设置
pidfile = "gunicorn.pid"
accesslog = "access.log"
errorlog = "error.log"
daemon = True  # 是否后台运行

启动后项目的目录下会生成access.log,error.loggunicorn.pid三个文件,gunicorn.pid中保存了gunicorn的主进程PID号,可以通过cat gunicorn.pid查看,当想要停止gunicorn时,直接kill 进程号即可杀死所有gunicorn进程。

4、结束gunicorn服务进程

使用ps -ef | grep gunicorn命令找出gunicorn所有进程。

[root@VM_0_12_centos ~]# ps -ef | grep gunicorn
root     16843 23035  0 Oct14 ?        00:00:02 /root/Envs/myflask/bin/python3.6 /root/Envs/myflask/bin/gunicorn -w 3 -b 172.17.0.12:80 app:app
root     22445 23035  0 Oct04 ?        00:00:15 /root/Envs/myflask/bin/python3.6 /root/Envs/myflask/bin/gunicorn -w 3 -b 172.17.0.12:80 app:app
root     22581 23035  0 Oct11 ?        00:00:05 /root/Envs/myflask/bin/python3.6 /root/Envs/myflask/bin/gunicorn -w 3 -b 172.17.0.12:80 app:app
root     23035     1  0 Sep27 ?        00:04:11 /root/Envs/myflask/bin/python3.6 /root/Envs/myflask/bin/gunicorn -w 3 -b 172.17.0.12:80 app:app

然后使用 kill -9 进程ID 命令来杀掉进程,注意,我们找到主进程杀掉即可,子进程会随之结束,在上例中,主进程号为23035.

[root@VM_0_12_centos ~]# kill -9 23035
[root@VM_0_12_centos ~]# ps -ef | grep gunicorn

杀掉进程后,稍等几秒,再使用ps -ef | grep gunicorn查看,发现gunicorn服务进程已全部杀掉。

参考:https://www.cnblogs.com/shenh/p/16824903.html
https://blog.csdn.net/Woodrow1994/article/details/113831985
https://zhuanlan.zhihu.com/p/618533248
https://zhuanlan.zhihu.com/p/488458470
http://www.manongjc.com/detail/12-nhpgmgnknsiysxf.html

  • 17
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

周小董

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值