10-Flask 部署:使用 gunicorn 部署 flask 项目.md

1、WSGI

1.1、WSGI 协议

Web 框架专注于业务逻辑、专注于HTML文档的生成。
Web 服务器用于处理和响应 HTTP 请求(HTTP 请求接收、建立连接、返回响应等)。
Web 框架和 Web 服务器之间的通信,需要一套双方都遵守的接口协议。这就是 WSGI 协议。

1.2、WSGI 容器

常用的 WSGI 容器有 Gunicorn 和 uWSGI,Gunicorn 直接用命令启动,不需要编写配置文件,相对 uWSGI 要容易很多。

2、并发模型

并发模型决定了服务器如何处理多个并发请求。主要的并发模型包括:

  • 线程模型:每个请求由一个线程处理,线程之间共享内存。
  • 进程模型:每个请求由一个独立的进程处理,进程之间不共享内存。
  • 异步模型:通过事件循环处理多个请求,常见于高并发的IO密集型应用。

Gunicorn支持多种并发模型,使其能够在不同的应用场景下提供最佳性能。

3、gunicorn 介绍

gunicorn(绿色独角兽 Green Unicorn 的简称)是一个 Python WSGI http server,只支持在 Unix 系统上运行,来源于 Ruby 的 unicorn 项目。

gunicorn 广泛兼容各种 web 框架,实现简单,服务器资源少,而且速度相当快。官方建议 Nginx+gunicorn 性能最好。

gunicorn 使用 prefork master-worker 模型(在 gunicorn 中,master 被称为 arbiter),gunicorn在启动时,会在主进程中预先 fork 出指定数量的 worker 进程来处理请求,即一个 master 进程管理多个 worker 进程(管理进程:master,工作进程:worker),所有请求和响应均由 Worker 处理。

Master 进程是一个简单的loop, 监听 worker 不同进程信号并且作出响应。这样可以减少频繁创建和销毁进程的开销,但是一个进程相对占用资源,会消耗大量内存。

gunicorn 推荐的 worker 数量是:(2*$num_cores)+1

为啥要用 gunicorn

Flask 是一个 Platform,他本身并不包括 Web Server,为了使用方便,Flask 内置了一个 Werkzeug wsgi server 但是这个 server 并不高效。 如果是工业部署的话, 就需要用 Gunicorn 去替代掉这个内置的 Wsgi Server。提升服务处理能力,比如,使用 Gunicorn 部署多个 Flask 应用实例,提升服务并发处理能力;使用 Gunicorn + gevent worker,monkeypatch 掉 Python 原生网路库,进一步提升处理能力,遇到 IO 等待时,挂起当前请求,处理其它请求。

简单说下几种部署方式

  • Flask 内置 WebServer + Flask App = 弱鸡版本的 Server, 单进程(单 worker) / 失败挂掉 / 不易 Scale
  • Gunicorn + Flask App = 多进程(多 worker) / 多线程 / 失败自动帮你重启 Worker / 可简单Scale
  • 多 Nginx + 多 Gunicorn + Flask App = 小型多实例 Web 应用,一般也会给 gunicorn 挂 supervisor

在生产环境中:一般都是请求的走向都是 Nginx->gunicorn->flask/django app

gunicorn 特点

  1. 兼容性强:支持多种 Web 框架,如 Django、Flask、Pyramid 等。
  2. 高性能:基于pre-fork worker模型,能充分利用多核CPU。
  3. 易于配置:提供了多种配置方式,包括命令行参数、配置文件和环境变量。
  4. 稳定性:在生产环境中广泛使用,经过了大量的实践检验。
  5. 简单易上手。

目前 gunicorn 只能运行在 Linux,不支持 windows。

4、gunicorn 安装

gunicorn 安装非常简单,使用命令 pip install gunicorn 即可。一般使用它,主要是为使用其异步的 worker 模型,还需要安装对应的异步模块。

1
2
3
4
$ pip install gunicorn
$ pip install greenlet # 使用异步必须安装
$ pip install eventlet # 使用eventlet workers
$ pip install gevent # 使用gevent workers

5、gunicorn 使用

这里使用 gunicorn 部署一个 Flask 项目。

如下例子,保存为 app.py

1
2
3
4
5
6
7
from flask import Flask
app = Flask(__name__)


@app.route("/")
def hello():
return "Hello World!"

在 shell 中输入你的启动配置,比如:

1
2
gunicorn -w 3 -b 127.0.0.1:8080 app:app
# 此处app:app中,第一个app为flask项目实例所在的包,第二个app为生成的flask项目实例

这样运行正常就可以启动服务器了。

如果要通过网络访问,则需要绑定不同的地址(也可以同时设置监听端口),设置 0.0.0.0 可以监听到所有 IP 的请求:

1
gunicorn -b 0.0.0.0:8080 app:app

监控和调试

可以使用多种工具监控和调试Gunicorn的性能。例如,使用Prometheus和Grafana进行监控,或者使用New Relic进行应用性能管理。

6、绑定端口

linux 通常会禁止绑定使用 1024 以下的端口,除非在 root 用户权限。很多人在使用 gunicorn 时试图将其绑定到 80 或者 443 端口,发现无效。如果想绑定到这些端口,常见的有如下的几种方法:

  • 使用 Nginx 代理转发。
  • sudo 启动 gunicorn。
  • 安装额外的程序。

7、结束 gunicorn 服务进程

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

1
2
3
4
5
# 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.

1
2
# kill -9 23035
# ps -ef | grep gunicorn

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

8、配置文件

使用 gunicorn -h 可以看到 gunicorn 有非常多的配置项,因此通常会写成一个配置文件来进行配置。

比如 gunicorn.conf 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# gunicorn.conf

# 监听地址
bind = "0.0.0.0:8000"

# 并行进程数
workers = 4

# 每个进程开启的线程数
threads = 2

# 监听队列
backlog = 2048

# pid 和 log 文件
pidfile = "log/gunicorn.pid"
# loglevel = "/logs/debug"
# logfile = "/logs/gun_debug.log"
accesslog = "log/access.log"
# access_log_format = "%(h)s %(t)s %(U)s %(q)s"
errorlog = "log/debug.log"

# 超时
timeout = 600

# 工作模式协程。使用 gevent 模式,还可以使用 sync 模式,默认的是 sync 模式
worker_class = "gevent"haodi

# 设置守护进程,将进程交给 supervisor 管理
daemon = "false"

# 最大客户端并发数量,默认情况下这个值为 1000。此设置将影响 gevent 和 eventlet 工作模式
worker_connections = 2000

# debug=False生产环境不用这个配置项,但调试的时候 debug=True 还是挺好用的。开启 debug 项后,在启动 gunicorn 的时候可以看到所有可配置项的配置
debug=False


capture_output = True

注意上面 log 项,如果需要将这些 log 文件统一放到 log 文件夹下,事先要先建好,不然运行时会报错。

运行代码为:

1
gunicorn --config gunicorn.conf main:app

9、Gunicorn 工作原理

Gunicorn 使用 pre-fork worker 模型,这意味着在处理请求之前,它会预先 fork 出多个 worker 进程。每个 worker 进程都是独立的,可以在不同的 CPU 核心上运行。这种模型的优点在于:

  • 隔离性好:每个 worker 进程都是独立的,如果一个进程崩溃,不会影响其他进程。
  • 扩展性强:可以根据需要增加或减少worker进程的数量。
  • 性能优越:可以充分利用多核CPU的并行处理能力。

Reference


10-Flask 部署:使用 gunicorn 部署 flask 项目.md
https://flepeng.github.io/021-Python-32-框架-Gunicorn-10-Gunicorn-简介和使用/
作者
Lepeng
发布于
2021年6月23日
许可协议