Flask 服务部署(Nginx+Gunicorn+Gevent)
2017-07-25
Flask 项目部署
我们开发好了一个flask
项目, 需要部署到线上服务器, 那我们的线上服务应该如何部署呢
基本的架构如下
Nginx
在开发环境, 我们一般直接运行Python服务, 启动了某个端口(一般是5000端口), 然后通过该端口进行开发调试
但线上环境一般不会直接这样提供服务, 一般的线上服务需要通过 Nginx
将外部请求转发到Python服务
这样有什么好处
- 隐藏python服务, 避免直接将python服务暴露出去
- 提高web服务的连接处理能力(Nginx)
- 作为反向代理, 提升python整体服务处理能力
我们可以配置的Nginx配置如下
upstream flask_servers {
server 127.0.0.1:9889;
}
server {
listen 80;
server_name dev.simple-cms.com;
access_log /data/logs/nginx/simple_cms_access.log main;
error_log /data/logs/nginx/simple_cms_error.log debug;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_redirect off;
proxy_pass http://flask_servers;
}
location ^~ /static {
root /data/www;
}
}
如果有多个python服务器, 可在upstream
下继续添加其他的python服务列表
Gunicorn + Gevent
Gunicorn
Guicorn
是一个python的一个 WSGI
的web sever, 什么是WSGI
Web Server <=====WSGI=====> Python APP
WSGI 其实是一种网关协议, 用以把http请求参数转换为python服务可以读取的内容, 这样在python的框架里能根据请求参数进行不同的业务处理了
Gunicorn
就是这么一种WSGI的实现, 他也是个web server, 可以直接提供对外的web服务, 但在一般的部署中, 他只是作为python服务的运行的容器
, 运行和管理
python应用程序
通过这个容器
, 从Nginx转发的请求就能转发到某个python app
了
除此之外, Gunicorn 还提供了多个运行参数, 常用的如下
-w 设置启动`python app` worker进程的数量
-k 运行模式(sync, gevent等等)
-b gunicorn 启动绑定的host和port
--max-requests 最大处理量, 单woker进程如果处理了超过该数量的请求, 该woker会平滑重启
Gevent
单进程直接运行Python app服务时, 当有两个并发请求过来时, 进程只能先处理一个请求, 等第一个请求处理完成后, 才能处理第二个, 势必影响用户的体验
那么单进程的时候, 如何能提高并发处理能力,
大多数情况下, 我们的服务中, 导致性能低下的原因是I/O
, 比如对数据库的读写, 发送Http请求等等, 当进程进行I/O
的时候, 是不占用CPU时间的, 这个时候, CPU可以被腾出来处理其他请求
Gevent就是完成这个工作的
幸运的是, 我们不需要再代码中自己实现这部分功能, Gunicorn 实现了Gevent模式的运行方式(-k
参数指定), 允许你的Python APP 更高性能的处理业务
通过 Gunicorn + Gevent, 我们可以如下启动
gunicorn --max-requests 300 --pid /tmp/flask.pid --timeout 3 -k gevent -w 2 -b 127.0.0.1:9889 run:app
从Nginx代理的请求, 就可以转发到Gunicorn
启动的9889
端口上了
supervisor
上面我们通过Gunicorn+Gevent
启动了Python服务, 在某些情况下, 我们的服务会停掉(系统掉电重启, 误杀, 不知道停了 :-( ),
我们不可能时刻都看着线上服务, 在这种情况下, 我们希望系统能自动拉起停掉的服务, 保证线上服务的稳定
supervisor 就是干这个的, supervisor会守护配置好的进程, 在进程停止后重新启动服务进程, 并保留日志
比如Nginx服务的配置可以如下
[program:nginx]
command = /usr/local/bin/nginx -g 'daemon off;' -c /usr/local/etc/nginx/nginx.conf
autostart = true
startsecs = 5
autorestart = true
startretries = 3
user = root
其中command
就是我们nginx服务
的启动命令,
同理, gunicorn启动的supervisor 配置如下
[program:gunicorn]
directory=/path/to/flask_app
command = /path/to/gunicorn --max-requests 3000 --pid /tmp/flask.pid --timeout 3 -k gevent -w 2 -b 127.0.0.1:9889 run:app autostart = true
startsecs = 5
autorestart = true
startretries = 3
user = www-data
以上配置好好, 执行
sudo supervisorctl -c /path/to/supervisord.ini update
就可以让supervisor 守护我们的gunicorn 服务
了
状态查看
sudo supervisorctl -c /path/to/supervisord.ini status
可以看到
gunicorn RUNNING pid 35640, uptime 0:00:14
状态是running
总结
以上, 我们实现了线上python服务的基础架构部署, 主要是针对python服务的部署, 基本遵循了文首的架构图
以上是我们在项目中实践的架构部署, 欢迎各位一起交流