####
部署方案flask+Gunicorn+gevent+supervisor
每个组件的作用:
1,. gunicorn:高性能WSGI服务器;
Gunicorn是一个unix上被广泛使用的高性能的Python WSGI UNIX HTTP Server。
和大多数的web框架兼容,并具有实现简单,轻量级,高性能等特点。
目前Gunicorn只能运行在Linux环境中,不支持windows平台
部署 Flask 应用时,为什么会需要 gunicorn 或 uWSGI?
简单说就是 Flask自带的wsgi性能低下
只适合你开发调试的时候用,
线上你必须用Gunicorn+Nginx才能获得更强的性能,和更高的安全性
下面我说一些废话:
django、flask 都有自带的http server,
仅仅是方便我们开发的时候调试代码而已
这些开源框架的维护者不可能投入大量精力来优化自带的wsgi服务器,
他们需要把更多的精力投入到框架自身的优化中,
因为服务器方面已经有Gunicorn/uWSGI、nginx等优秀的开源解决方案
假设我们用自带的来部署到线上,会有什么问题呢?
性能很差,差到不好意思出门见人(如果你的网站就几十个人访问,那性能应该问题不大)
最后我个人建议的方案是 flask+Gunicorn+gevent+supervisor+nginx
所以说为什么使用Gunicorn,简单点就是为了并发。利用异步,提高性能。
2. gevent:把Python同步代码变成异步协程的库;
gevent:gunicorn 默认使用同步阻塞的网络模型(-k sync),对于大并发的访问可能表现不够好,我们很方便地顺手套一个gevent来增加并发量
3,supervisor:监控服务进程的工具;
web服务跑起来之后,为了保证服务的稳定性,需要加一个收获进程。supervisor非常好用,配置也简单方便,它是一个用 Python 写的进程管理工具,可以很方便的用来启动、重启、关闭进程(不仅仅是 Python 进程)。除了对单个进程的控制,还可以同时启动、关闭多个进程,比如很不幸的服务器出问题导致所有应用程序都被杀死,此时可以用 supervisor 同时启动所有应用程序而不是一个一个地敲命令启动。
nginx一般不会莫名其妙被关闭,但gunicorn是一个进程,完成有有可能因为一些原因被关闭或者阻塞,为了保证gunicorn进程,需要使用看护进程插件。这里使用supervisor来解决这个问题。
supervisor专门用户linux端进程管理,
###
启动主程序的命令传递:supervisor->gunicorn->flask
###
看着步骤很多,其实除了Gunicorn都不是必须的,Supervisor和Nginx你要是不想使用其实也可以不使用,我说得比较啰嗦,不过其实很容易。
####
第一步,准备一个简单的flask项目,
很简单只需要一个文件,
from flask import Flask app = Flask(__name__) @app.route('/') def alldata(): return '<h1>Hello World!</h1>' # if __name__ == "__main__": """初始化,debug=True""" app.run(host='0.0.0.0', port=9876, debug=True)
###
Flask==1.1.2 gevent==21.8.0 gunicorn==20.1.0
supervisor==4.2.2
###
第二步,gunicorn 安装,Gevent安装
pip install gunicorn
pip install gevent
pip install supervisor
###
第三步,在根目录下新建文件 /gunicorn.conf.py
启动测试
gunicorn start:app -c gunicorn.conf.py
用这种py文件的方式启动是比较简单的,
否则就要用命令行的方式启动,比较麻烦:
gunicorn --workers 3 --bind 0.0.0.0:5000 --user nginx --worker-class gevent start:app
#####
第四步:supervisor
你要先搞懂,supervisor和gunicorn,和flask的关系,
其次你要搞懂,supervisor和docker的关系,
配置
[supervisord] nodaemon=true [program:flask_docker_gunicorn_supervisor] command=gunicorn -w4 -b0.0.0.0:8888 app:app ; supervisor启动命令
###
第五步,Dockerfile
FROM python:3.8.5-slim-buster WORKDIR /usr/src/app COPY requirements.txt ./ RUN pip install --no-cache-dir -r requirements.txt COPY . . CMD ["supervisord","-n","-c","supervisord.conf"]
##
第五步构建
完成这两个文件的创建之后,执行如下命令,就可以开始构建Docker镜像:
sudo docker build -t 'testflask' .
构建完成之后,通过如下命令查看镜像列表,可以发现testflask显示在其中:
sudo docker images
####
第六步,运行,
接下来,我们可以push镜像到镜像仓库进行分发,这里我们就在本机运行进行演示。
需要注意,公司的私有代码,不要push到公网的镜像仓库上
运行如下命令,临时运行docker镜像:
sudo docker run -it --rm -p 8888:8888 testflask
#####
supervisor和语言没有关系,任何代码语言都可以使用这个
对于有些进程,我们不希望它出现意外的崩溃,如果万一崩溃了,也希望可以自动能够重启,而不是手动去启动他们,万一半夜崩了,那不得半夜起来重启服务?那滋味一定很酸爽。很典型的一种就是web服务,按照道理来讲,服务器不宕机,应该是需要一直运行下去的。可是天意不可测,万一哪天突然崩了呢? 所以我们需要一种机制,确保web服务崩了依然可以自启。今天要介绍的supervisor就是作为一种进程守护,来监听web服务,一旦web挂掉,supervisor会让其自启。确保web服务器不会处于挂掉状态
supervisor安装
pip install supervisor
echo_supervisord_conf > supervisor.conf # 生成 supervisor 默认配置文件
vim supervisor.conf # 修改 supervisor 配置文件,添加 gunicorn 进程管理
另外一种安装方法:
配置好yum源后,可以直接安装【本文安装方法】
yum install supervisor
查看安装的版本:
supervisord -v
######
使用 supervisor 来管理 项目
[program:myapp] command=/home/rsj217/rsj217/myproject/venv/bin/gunicorn -w4 -b0.0.0.0:2170 myapp:app ; supervisor启动命令 directory=/home/rsj217/rsj217/myproject ; 项目的文件夹路径 startsecs=0 ; 启动时间 stopwaitsecs=0 ; 终止等待时间 autostart=false ; 是否自动启动 autorestart=false ; 是否自动重启 stdout_logfile=/home/rsj217/rsj217/myproject/log/gunicorn.log ; log 日志 stderr_logfile=/home/rsj217/rsj217/myproject/log/gunicorn.err ; 错误日志
supervisor的基本使用命令
supervisord -c supervisor.conf 通过配置文件启动supervisor supervisorctl -c supervisor.conf status 察看supervisor的状态 supervisorctl -c supervisor.conf reload 重新载入 配置文件 supervisorctl -c supervisor.conf start [all]|[appname] 启动指定/所有 supervisor管理的程序进程 supervisorctl -c supervisor.conf stop [all]|[appname] 关闭指定/所有 supervisor管理的程序进程
使用 supervisor 来管理 nginx。这里需要注意一个问题,linux的权限问题。nginx是sudo的方式安装,启动的适合也是 root用户,那么我们现在也需要用 root用户启动supervisor。增加下面的配置文件
[program:nginx] command=/usr/sbin/nginx startsecs=0 stopwaitsecs=0 autostart=false autorestart=false stdout_logfile=/home/rsj217/rsj217/myproject/log/nginx.log stderr_logfile=/home/rsj217/rsj217/myproject/log/nginx.err
####
supervisor 还有一个web的管理界面,可以激活。更改下配置
[inet_http_server] ; inet (TCP) server disabled by default
port=127.0.0.1:9001 ; (ip_address:port specifier, *:port for all iface)
username=user ; (default is no username (open server))
password=123 ; (default is no password (open server))
[supervisorctl]
serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL for a unix socket
serverurl=http://127.0.0.1:9001 ; use an http:// url to specify an inet socket
username=user ; should be same as http_username if set
password=123 ; should be same as http_password if set
;prompt=mysupervisor ; cmd line prompt (default "supervisor")
;history_file=~/.sc_history ; use readline history if available
#####