flask中gunicorn的使用

最近模型部署用flask给接口,模型实验室的部署流程中需用gunicorn来部署flask服务。为什么要用gunicorn呢,简单点就是为了并发。

1、模块安装

pip install flask
pip install gunicorn

2、用flask写一个简单的web服务

# main.py

from
flask import Flask app = Flask(__name__) @app.route('/') def index(): return 'hello world' def main(): app.run(debug=True) if __name__ == '__main__': main()

3、启动

  我们知道直接运行main.py函数就可以启动flask服务,但是我们这里要用gunicorn,也很简单

gunicorn main:app
  • main是flask的启动python文件,我们这是main.py,
  • app则是flask应用程序实例,我们mian.py里实例名为app
这样运行的话, gunicorn 默认作为一个监听 127.0.0.1:8000 的web server,可以在本机通过: http://127.0.0.1:8000 访问。

 如果要通过网络访问,则需要绑定不同的地址(也可以同时设置监听端口),设置0.0.0.0可以监听到所有ip的请求:

gunicorn -b 0.0.0.0:8080 main:app

在多核服务器上,为了支持更多的并发访问并充分利用资源,可以使用更多的 gunicorn 进程:

gunicorn -w 4 -b 0.0.0.0:8080 main:app
  • -b 表示 gunicorn 开发的访问地址 
  • -w 表示工作进程数

4、配置文件

  通过gunicorn -h可以看到gunicorn有非常多的配置项,因此通常会写成一个配置文件来进行配置。

  比如我这边写成gunicorn.conf文件

# gunicorn.conf

bind = "0.0.0.0:5000"
workers = 4
backlog = 2048
pidfile = "log/gunicorn.pid"
accesslog = "log/access.log"
errorlog = "log/debug.log"
timeout = 600
debug=False
capture_output = True

debug=False: 生产环境不用这个配置项,但调试的时候debug=True还是挺好用的。而且,开启debug项后,在启动gunicorn的时候可以看到所有可配置项的配置

注意上面log项,如果需要将这些log文件统一放到log文件夹下,事先要先建好,不然运行时会报错。

运行代码为:

gunicorn --config gunicorn.conf main:app

 

 5、gunicorn启动flask后,访问api却报404

在工作中遇到一个问题,gunicorn启动flask后,访问api却报404。让我百思不得其解。

启动文件run.py如下:

from settings import app
from api import regist_url


if __name__ == '__main__':
    regist_url()
    app.run(debug=True, host='0.0.0.0', port=6500)

gunicorn正常启动flask后,服务器显示启动正常

于是我兴奋地打开Postman想试一试接口测试,结果发现报404错误,即网址无法访问。而我直接用python run.py启动时是可以访问的。

一番冲浪后才发现问题所在。python只有在这个脚本是python解释器的时候,才会把__name__的值置为__main__,但是用gunicorn启动的时候,这个脚本是被import 导入了,所以它根本不会执行__name__ == '__main__'之后的命令。而用python run.py直接启动的时候,这个文件就是python解释器的入口文件,__main__之后的文件会被执行。回过来说gunicorn,gunicorn启动时,它只需要知道app是哪个就可以了,因为gunicorn配置文件中已经配置了host和port,所以它可以成功启动。如果把`run.py`代码改成下面这样也会报错。

from settings import app
from api import regist_url

regist_url()
app.run(debug=True, host='0.0.0.0', port=6500)

因为gunicorn的启动时已经启动了一个app了,然后`app.run`这行代码又要启动一个app,端口被占用了。所以最好是写成下面的方式,这样可以同时兼容gunicorn和python启动两种方式。

from settings import app
from api import regist_url

regist_url()

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=6500)

 

 

 

posted @ 2020-04-01 18:20  理想几岁  阅读(20716)  评论(0编辑  收藏  举报