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 前使用诸如 nginx 或 Apache 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 提供了使用 gevent 或 eventlet 的 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