Gunicorn

Gunicorn 是一个纯 Python 实现的 WSGI 服务器,配置简单,提供多种 worker 实现以进行性能调优。

  • 通常可以很容易地集成到各种托管平台中。

  • 不支持 Windows(但可运行在 WSL 上)。

  • 安装便捷,无需额外依赖或编译过程。

  • 内置对 gevent 和 eventlet 的异步 worker 支持。

本页介绍了运行 Gunicorn 的基础内容。请务必阅读其 documentation,并使用 gunicorn --help 查看可用功能。

安装

Gunicorn 安装非常简单,无需外部依赖或编译。它仅在 WSL 上支持 Windows。

创建一个虚拟环境,安装你的应用,然后安装 gunicorn

$ cd hello-app
$ python -m venv .venv
$ . .venv/bin/activate
$ pip install .  # install your application
$ pip install gunicorn

运行

使用 Gunicorn 运行 Flask 应用时,只需要一个参数,指定如何加载你的 Flask 应用。语法为 {module_import}:{app_variable}。其中 module_import 是指向应用模块的导入路径,app_variable 是应用实例的变量名。如果使用的是工厂函数模式,也可以传入函数调用(包含参数)。

# equivalent to 'from hello import app'
$ gunicorn -w 4 'hello:app'

# equivalent to 'from hello import create_app; create_app()'
$ gunicorn -w 4 'hello:create_app()'

Starting gunicorn 20.1.0
Listening at: http://127.0.0.1:8000 (x)
Using worker: sync
Booting worker with pid: x
Booting worker with pid: x
Booting worker with pid: x
Booting worker with pid: x

-w 选项用于指定要运行的进程数量;一个推荐的初始值是 CPU * 2。默认只有 1 个 worker,这对于默认的 worker 类型来说可能不够。

默认情况下不会显示每个请求的日志,只会显示 worker 信息和错误。若要将访问日志输出到 stdout,使用 --access-logfile=- 选项。

外部绑定

不建议以 root 身份运行 Gunicorn,因为这会导致应用代码也以 root 身份运行,存在安全隐患。然而,这也意味着无法绑定到 80 或 443 端口。此时应在 Gunicorn 前使用诸如 nginxApache httpd 的反向代理服务器。

你可以使用 -b 0.0.0.0 选项将服务器绑定到所有外部 IP 上的非特权端口。但在使用反向代理的设置中不要这样做,否则可能绕过代理访问服务。

$ gunicorn -w 4 -b 0.0.0.0 'hello:create_app()'
Listening at: http://0.0.0.0:8000 (x)

注意:0.0.0.0 不是一个可以在浏览器中访问的有效地址,浏览器中应使用具体的 IP 地址。

异步支持:gevent 或 eventlet

默认的同步 worker 适用于大多数场景。如果你需要异步支持,Gunicorn 提供了使用 geventeventlet 的 worker。这与 Python 的 async/await 或 ASGI 服务器规范不同。你必须在自己的代码中实际使用 gevent 或 eventlet,才能真正发挥这些 worker 的优势。

当使用 gevent 或 eventlet 时,必须使用 greenlet>=1.0,否则像 request 这样的上下文局部变量将无法按预期工作。 如果使用 PyPy,则要求 PyPy 版本不低于 7.3.7。

使用 gevent:

$ gunicorn -k gevent 'hello:create_app()'
Starting gunicorn 20.1.0
Listening at: http://127.0.0.1:8000 (x)
Using worker: gevent
Booting worker with pid: x

使用 eventlet:

$ gunicorn -k eventlet 'hello:create_app()'
Starting gunicorn 20.1.0
Listening at: http://127.0.0.1:8000 (x)
Using worker: eventlet
Booting worker with pid: x