最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

【已解决】Mac本地用gunicorn部署启动Flask应用

Flask crifan 2628浏览 0评论

折腾:

【已解决】把Python3的pipenv的Flask部署到CentOS服务器上

期间,先去Mac本地中,折腾用gunicorn去部署和启动Flask应用。

Gunicorn deploy flask

How To Serve Flask Applications with Gunicorn and Nginx on Ubuntu 16.04 | DigitalOcean

Deploy flask app with nginx using gunicorn and supervisor

Flask + Gunicorn + Nginx 部署 – Ray Liang – 博客园

独立 WSGI 容器 — Flask 0.10.1 文档

Deploy Flask Applications with Gunicorn and Nginx on Ubuntu 14.04

How to setup Flask with gunicorn and nginx with example | Tech Tutorials

Flask Gunicorn Supervisor Nginx 项目部署小总结

然后先去折腾简单的gunicorn

等熟悉了后,再去放到supervisor中

先去安装:

<code>➜  robotDemo pipenv install gunicorn
Installing gunicorn…
Collecting gunicorn
  Downloading https://files.pythonhosted.org/packages/64/32/becbd4089a4c06f0f9f538a76e9fe0b19a08f010bcb47dcdbfbc640cdf7d/gunicorn-19.7.1-py2.py3-none-any.whl (111kB)
Installing collected packages: gunicorn
Successfully installed gunicorn-19.7.1

Adding gunicorn to Pipfile's [packages]…
Pipfile.lock (36c54e) out of date, updating to (cdbe9e)…
Locking [dev-packages] dependencies…
Locking [packages] dependencies…
Updated Pipfile.lock (cdbe9e)!
Installing dependencies from Pipfile.lock (cdbe9e)…
  🐍   ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 13/13 — 00:00:03
To activate this project's virtualenv, run the following:
 $ pipenv shell
➜  robotDemo pipenv graph
Flask-PyMongo==0.5.1
  - Flask [required: &gt;=0.8, installed: 0.12.2]
    - click [required: &gt;=2.0, installed: 6.7]
    - itsdangerous [required: &gt;=0.21, installed: 0.24]
    - Jinja2 [required: &gt;=2.4, installed: 2.10]
      - MarkupSafe [required: &gt;=0.23, installed: 1.0]
    - Werkzeug [required: &gt;=0.7, installed: 0.14.1]
  - PyMongo [required: &gt;=2.5, installed: 3.6.1]
Flask-RESTful==0.3.6
  - aniso8601 [required: &gt;=0.82, installed: 3.0.0]
  - Flask [required: &gt;=0.8, installed: 0.12.2]
    - click [required: &gt;=2.0, installed: 6.7]
    - itsdangerous [required: &gt;=0.21, installed: 0.24]
    - Jinja2 [required: &gt;=2.4, installed: 2.10]
      - MarkupSafe [required: &gt;=0.23, installed: 1.0]
    - Werkzeug [required: &gt;=0.7, installed: 0.14.1]
  - pytz [required: Any, installed: 2018.4]
  - six [required: &gt;=1.3.0, installed: 1.11.0]
gunicorn==19.7.1

</code>

现在本地Mac中,先进入pipenv的虚拟环境中:

<code>➜  robotDemo pipenv shell
Spawning environment shell (/bin/zsh). Use 'exit' to leave.
. /Users/crifan/.local/share/virtualenvs/robotDemo-HXjMJQEQ/bin/activate
➜  robotDemo . /Users/crifan/.local/share/virtualenvs/robotDemo-HXjMJQEQ/bin/activate
➜  robotDemo which gunicorn
/Users/crifan/.local/share/virtualenvs/robotDemo-HXjMJQEQ/bin/gunicorn
➜  robotDemo gunicorn --version
gunicorn (version 19.7.1)
</code>

再去运行试试,运行之前,先去搞清楚gunicorn的参数的含义:

【已解决】部署Flask的gunicorn的最后一个参数的含义

而在看help信息期间:

  • 待会抽空试试reload参数

  • 注意到–chdir CHDIR,默认是当前目录:

    • /Users/crifan/dev/dev_root/company/naturling/projects/robotDemo

然后就是先去命令行中试试:

<code>➜  robotDemo gunicorn -w 4 -b 127.0.0.1:32851 app:app
[2018-04-20 11:56:43 +0800] [2640] [INFO] Starting gunicorn 19.7.1
[2018-04-20 11:56:43 +0800] [2640] [INFO] Listening at: http://127.0.0.1:32851 (2640)
[2018-04-20 11:56:43 +0800] [2640] [INFO] Using worker: sync
[2018-04-20 11:56:43 +0800] [2643] [INFO] Booting worker with pid: 2643
[2018-04-20 11:56:43 +0800] [2644] [INFO] Booting worker with pid: 2644
[2018-04-20 11:56:43 +0800] [2645] [INFO] Booting worker with pid: 2645
[2018-04-20 11:56:43 +0800] [2646] [INFO] Booting worker with pid: 2646
[2018-04-20 11:56:43,624 INFO app.py:59 &lt;module&gt;] api=&lt;flask_restful.Api object at 0x10536a780&gt;
[2018-04-20 11:56:43,626 INFO app.py:59 &lt;module&gt;] api=&lt;flask_restful.Api object at 0x104f69710&gt;
[2018-04-20 11:56:43,629 INFO app.py:80 &lt;module&gt;] purePymongo=MongoClient(host=['47.96.131.109:32018'], document_class=dict, tz_aware=False, connect=True, authsource='gridfs')
[2018-04-20 11:56:43,629 INFO app.py:80 &lt;module&gt;] purePymongo=MongoClient(host=['47.96.131.109:32018'], document_class=dict, tz_aware=False, connect=True, authsource='gridfs')
[2018-04-20 11:56:43,670 INFO app.py:59 &lt;module&gt;] api=&lt;flask_restful.Api object at 0x10576a7f0&gt;
[2018-04-20 11:56:43,673 INFO app.py:80 &lt;module&gt;] purePymongo=MongoClient(host=['47.96.131.109:32018'], document_class=dict, tz_aware=False, connect=True, authsource='gridfs')
[2018-04-20 11:56:43,702 INFO app.py:59 &lt;module&gt;] api=&lt;flask_restful.Api object at 0x1065feef0&gt;
[2018-04-20 11:56:43,704 INFO app.py:80 &lt;module&gt;] purePymongo=MongoClient(host=['47.96.131.109:32018'], document_class=dict, tz_aware=False, connect=True, authsource='gridfs')
</code>

然后去GET测试一下:

gunicorn中输出对应的log:

<code>[2018-04-20 11:57:13,018 INFO app.py:104 get] parser=&lt;flask_restful.reqparse.RequestParser object at 0x10622e0f0&gt;
[2018-04-20 11:57:13,021 INFO app.py:107 get] parsedArgs={'q': 'play a morning song'}
[2018-04-20 11:57:13,024 INFO app.py:113 get] q=play a morning song
[2018-04-20 11:57:13,026 INFO app.py:122 get] foundSongName=&lt;_sre.SRE_Match object; span=(0, 19), match='play a morning song'&gt;
[2018-04-20 11:57:13,029 INFO app.py:128 get] songName=morning
[2018-04-20 11:57:13,031 INFO app.py:150 get] filenameRegex=re.compile('morning', re.IGNORECASE)
[2018-04-20 11:57:13,032 INFO app.py:156 get] findFileCursor=&lt;gridfs.grid_file.GridOutCursor object at 0x10622e358&gt;
[2018-04-20 11:57:13,197 INFO app.py:158 get] findFileCount=0
</code>

在搞定了命令行之后,去参考:

Gunicorn运行与配置 – 简书

“* -D, –daemon

以守护进程形式来运行Gunicorn进程,其实就是将这个服务放到后台去运行。

配置文件必须是一个python文件,只是将命令行中的参数写进py文件中而已,如果需要设置哪个参数,则在py文件中为该参数赋值即可。”

去换成配置文件,然后多加点参数,看看效果。还不错:

配置文件:

gunicorn_config.py

<code>import multiprocessing

currentRootPath = "/Users/crifan/dev/dev_root/company/naturling/projects/robotDemo"
reload = True                                   #当代码改变时自动重启服务
bind = '127.0.0.1:32851'                        #绑定ip和端口号
backlog = 512                                   #监听队列
chdir = currentRootPath                         #gunicorn要切换到的目的工作目录
timeout = 30                                    #超时
worker_class = 'sync'                           #默认的是sync模式
workers = multiprocessing.cpu_count() * 2 + 1   #进程数
threads = 2                                     #指定每个进程开启的线程数
loglevel = 'info'                               #日志级别,这个日志级别指的是错误日志的级别,而访问日志的级别无法设置
access_log_format = '%(t)s %(p)s %(h)s "%(r)s" %(s)s %(L)s %(b)s %(f)s" "%(a)s"'    #设置gunicorn访问日志格式,错误日志无法设置
"""
其每个选项的含义如下:
h          remote address
l          '-'
u          currently '-', may be user name in future releases
t          date of the request
r          status line (e.g. ``GET / HTTP/1.1``)
s          status
b          response length or '-'
f          referer
a          user agent
T          request time in seconds
D          request time in microseconds
L          request time in decimal seconds
p          process ID
"""

accesslog = currentRootPath + "/logs/gunicorn_access.log"      #访问日志文件
errorlog  = currentRootPath + "/logs/gunicorn_error.log"       #错误日志文件
</code>

然后去调用:

<code>gunicorn -c gunicorn_config.py app:app
</code>

输出效果是:

<code>  robotDemo gunicorn -c gunicorn_config.py app:app
[2018-04-20 13:45:16,938 INFO app.py:59 &lt;module&gt;] api=&lt;flask_restful.Api object at 0x111ae89e8&gt;
[2018-04-20 13:45:16,945 INFO app.py:80 &lt;module&gt;] purePymongo=MongoClient(host=['47.96.131.109:32018'], document_class=dict, tz_aware=False, connect=True, authsource='gridfs')
[2018-04-20 13:45:17,087 INFO app.py:59 &lt;module&gt;] api=&lt;flask_restful.Api object at 0x111ae7978&gt;
[2018-04-20 13:45:17,094 INFO app.py:80 &lt;module&gt;] purePymongo=MongoClient(host=['47.96.131.109:32018'], document_class=dict, tz_aware=False, connect=True, authsource='gridfs')
[2018-04-20 13:45:17,116 INFO app.py:59 &lt;module&gt;] api=&lt;flask_restful.Api object at 0x111ae8a58&gt;
[2018-04-20 13:45:17,122 INFO app.py:80 &lt;module&gt;] purePymongo=MongoClient(host=['47.96.131.109:32018'], document_class=dict, tz_aware=False, connect=True, authsource='gridfs')
[2018-04-20 13:45:17,253 INFO app.py:59 &lt;module&gt;] api=&lt;flask_restful.Api object at 0x111ae8ac8&gt;
[2018-04-20 13:45:17,262 INFO app.py:80 &lt;module&gt;] purePymongo=MongoClient(host=['47.96.131.109:32018'], document_class=dict, tz_aware=False, connect=True, authsource='gridfs')
[2018-04-20 13:45:17,361 INFO app.py:59 &lt;module&gt;] api=&lt;flask_restful.Api object at 0x111ae8b38&gt;
[2018-04-20 13:45:17,367 INFO app.py:80 &lt;module&gt;] purePymongo=MongoClient(host=['47.96.131.109:32018'], document_class=dict, tz_aware=False, connect=True, authsource='gridfs')
[2018-04-20 13:45:17,387 INFO app.py:59 &lt;module&gt;] api=&lt;flask_restful.Api object at 0x111ae8c18&gt;
[2018-04-20 13:45:17,392 INFO app.py:80 &lt;module&gt;] purePymongo=MongoClient(host=['47.96.131.109:32018'], document_class=dict, tz_aware=False, connect=True, authsource='gridfs')
[2018-04-20 13:45:17,393 INFO app.py:59 &lt;module&gt;] api=&lt;flask_restful.Api object at 0x111ae8ba8&gt;
[2018-04-20 13:45:17,399 INFO app.py:80 &lt;module&gt;] purePymongo=MongoClient(host=['47.96.131.109:32018'], document_class=dict, tz_aware=False, connect=True, authsource='gridfs')
[2018-04-20 13:45:17,405 INFO app.py:59 &lt;module&gt;] api=&lt;flask_restful.Api object at 0x111ae9c88&gt;
[2018-04-20 13:45:17,426 INFO app.py:80 &lt;module&gt;] purePymongo=MongoClient(host=['47.96.131.109:32018'], document_class=dict, tz_aware=False, connect=True, authsource='gridfs')
[2018-04-20 13:45:17,428 INFO app.py:59 &lt;module&gt;] api=&lt;flask_restful.Api object at 0x111aeacf8&gt;
[2018-04-20 13:45:17,431 INFO app.py:80 &lt;module&gt;] purePymongo=MongoClient(host=['47.96.131.109:32018'], document_class=dict, tz_aware=False, connect=True, authsource='gridfs')
</code>

其中可见,worker=9=4(CPU个数) * 2 + 1

同时试试:

<code>--reload              Restart workers when code changes. [False]
</code>

参数,还真是可以实现:

改动之前效果:

当代码改动:

自动重启服务,然后有新的GET后可以输出的刚刚代码改动后的新的效果了:

同时看看log输出效果:

【总结】

此处,对于Mac本地的pipenv的虚拟环境中使用gunicorn去部署Flask的应用,做法是:

1.pipenv中安装gunicorn

<code>pipenv install gunicorn
</code>

2.命令行中直接调用

<code>gunicorn -w 4 -b 127.0.0.1:32851 app:app
</code>

其中:

  • -w=–worker=进程数

  • -b=–bind=监听的地址和端口

  • app:app:

    • 第一个app:指的是此处的app.py

      • ls -l

      • -rw-r–r–  1 crifan  staff   8.3K  4 20 13:46 app.py

    • 第二个app:指的是(app.py中的)Flask的实例的名字叫做app

      • app = Flask(__name__)

3.也可以用配置文件去调用

gunicorn_config.py

<code>import multiprocessing

currentRootPath = "/Users/crifan/dev/dev_root/company/naturling/projects/robotDemo"
reload = True                                   #当代码改变时自动重启服务
bind = '127.0.0.1:32851'                        #绑定ip和端口号
backlog = 512                                   #监听队列
chdir = currentRootPath                         #gunicorn要切换到的目的工作目录
timeout = 30                                    #超时
worker_class = 'sync'                           #默认的是sync模式
workers = multiprocessing.cpu_count() * 2 + 1   #进程数
threads = 2                                     #指定每个进程开启的线程数
loglevel = 'info'                               #日志级别,这个日志级别指的是错误日志的级别,而访问日志的级别无法设置
access_log_format = '%(t)s %(p)s %(h)s "%(r)s" %(s)s %(L)s %(b)s %(f)s" "%(a)s"'    #设置gunicorn访问日志格式,错误日志无法设置
"""
其每个选项的含义如下:
h          remote address
l          '-'
u          currently '-', may be user name in future releases
t          date of the request
r          status line (e.g. ``GET / HTTP/1.1``)
s          status
b          response length or '-'
f          referer
a          user agent
T          request time in seconds
D          request time in microseconds
L          request time in decimal seconds
p          process ID
"""

accesslog = currentRootPath + "/logs/gunicorn_access.log"      #访问日志文件
errorlog  = currentRootPath + "/logs/gunicorn_error.log"       #错误日志文件
</code>

调用方式:

<code>gunicorn -c gunicorn_config.py app:app
</code>

即可。

其中指定了输出的access和error的log。

备注1:

从:

gunicorn 部署 flask 应用 – CSDN博客

“日志配置参数,命令行中使用 –access-logfile ,而在文件配置中使用 accesslog。”

-》刚刚自己也是注意到:

命令行参数是

<code>  --error-logfile FILE, --log-file FILE
                        The Error log file to write to. [-]
</code>

而配置文件中的是:

<code>accesslog
</code>

详见:Settings — Gunicorn 19.7.1 documentation

备注2:

刚才参考别人配置时,就把worker_class从gevent换成了sync

否则需要我去安装gevent

然后看到:

Flask+Gunicorn+Gevent+Supervisor+Nginx生产环境部署-xujpxm-51CTO博客

“3). gevent:把Python同步代码变成异步协程的库;

-k: 指定worker-class模式,默认为sync,这里用gevent使之变为异步协程,提高性能。”

-》所以:

如果后续需要把同步换异步,再去考虑把gunicorn的worker_class从sync换gevent

转载请注明:在路上 » 【已解决】Mac本地用gunicorn部署启动Flask应用

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
87 queries in 0.199 seconds, using 22.11MB memory