基本环境
最简单的Flask Web应用:
新建文件夹myproject,里面就一个文件:myapp.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'Hi! It works!'
if __name__=='__main__':
app.run(host='0.0.0.0')
想启动该应用,只要运行python myapp.py就可以在浏览器http://localhost:5000看到运行结果了。开心!
然鹅,这里的问题是:这个应用是单进程单线程的,如果在多个用户(高并发)的场景,这个就要跪了
为什么使用Gunicorn
Flask 作为一个 Web 框架,内置了一个 webserver, 但这自带的 Server 到底能不能用?
官网的介绍:
While lightweight and easy to use, Flask’s built-in server is not suitable for production as it doesn’t scale well. Some of the options available for properly running Flask in production are documented here.
很显然,内置的 webserver 是能用的。但不适合放在生产环境。这个 server 本来就是给开发者用的。框架本身并不提供生产环境的 web 服务器,SpringBoot 这种内置 Tomcat 生产级服务器 是例外。
假设我们使用的是 Nginx+Flask Run 来当作生产环境,全部部署在一台机器上。劣势如下:
- 单 Worker。
只有一个进程在跑所有的请求,而由于实现的简陋性,内置 webserver 很容易卡死。并且只有一个 Worker 在跑请求。在多核 CPU 下,仅仅占用一核。当然,其实也可以多起几个进程。 - 缺乏 Worker 的管理。
接上,加入负载量上来了,Gunicorn 可以调节 Worker 的数量。而这个东西,内置的 Webserver 是不适合做这种事情的。一言以蔽之,太弱,几个请求就打满了。
Gunicorn(绿色独角兽)是一个Python WSGI的HTTP服务器。从Ruby的独角兽(Unicorn )项目移植。该Gunicorn服务器与各种Web框架兼容,实现非常简单,轻量级的资源消耗。Gunicorn直接用命令启动,不需要编写配置文件,相对uWSGI要容易很多。
Gunicorn 作为 Server 相对而言可以有什么提升?
- gunicorn 的优点如下, 帮我 scale worker, 进程挂了帮我重启
- 用 python 的框架 flask/django/webpy 配置起来都差不多。
- 还有信号机制。可以支持多种配置。
- 其他:在管理 worker 上,使用了 pre-fork 模型,即一个 master 进程管理多个 worker 进程,所有请求和响应均由 Worker 处理。Master 进程是一个简单的 loop, 监听 worker 不同进程信号并且作出响应。 比如接受到 TTIN 提升 worker 数量,TTOU 降低运行 Worker 数量。如果 worker 挂了,发出 CHLD, 则重启失败的 worker, 同步的 Worker 一次处理一个请求。 PS: 如果没有静态资源并且无需反向代理的话,抛弃 Nginx 直接使用 Gunicorn 和 Flask app 也能搞定。采用多进程时,只需要占用 1 个端口即可,收到的http请求自动分发到各个worker进程。同时 worker_class 选用 gevent 异步协程方式,测试发现性能会有很大提升。
架构:
nginx(反向代理)-> gunicorn(with gevent)-> flask server -> supervisor
nginx 只使用反向代理功能,不再作负载均衡。负载均衡在 gunicorn 侧实现,采用轮询方式。
Gunicorn
这时候Gunicorn登场了,它就是来解决这个高并发的问题的。它全名叫Green Unicorn,是一个被广泛使用的高性能的Python WSGI Unix HTTP服务器。
Gunicorn 是python中的WSGI容器,pre-fork worker模式,优点就是配置简单,轻量级的资源消耗,以及高性能。
安装
$ pip install gunicorn
相关配置:
bind = '0.0.0.0:17123' # 监听地址和端口
backlog = 2048 # 最大挂起连接数
timeout = 30 # 超时时间
worker_class = 'gevent' # worker 进程的工作方式。目前选用 gevent 异步协程方式
worker_connections = 65535 # 客户端最大同时连接数
workers = 1 # 处理请求的 worker 进程数量,多进程
threads = 1 # 每个 worker 进程的线程数。采用 gevent 协程方式时,配置 1 即可
使用
在命令行下,键入:
$ gunicorn -w 4 myapp:app
可以看到输出:
[2018-10-25 20:21:12 +0800] [28597] [INFO] Starting gunicorn 19.9.0
[2018-10-25 20:21:12 +0800] [28597] [