当前位置:   article > 正文

centos部署python flask_python上手实践 -- docker+nginx+gunicorn+flask项目部署

centos用docker搭建py+flask+gunicorn环境

02d4924acc661afefc9042720756b53b.png

flask属于轻量级python的web框架,其流行程度可以与django媲美。因为是轻量型,所以对于开发一些中小型项目就非常方便。不过flask自带的server速度较慢,测试环境还可以,真正实际使用起来还是很多问题。同时在部署时会移植到linux系统中,稳定性更好。

1.使用虚拟环境创建flask项目

在使用flask来开发项目时,为了保证项目移植的顺平性(如在windows中开发的项目移植到linux中),通常会采用env虚拟环境方式,将pip安装的一系列第三方库放在虚拟环境env目录下。移动整个项目工程也就会将虚拟环境迁移走。

(1)建立虚拟环境env,并激活使用

首先新建一个flask工程目录,并使用python -m venv env命令创建虚拟环境目录:

  1. mkdir Flask_Proj
  2. cd Flask_Proj
  3. python -m venv env #创建虚拟环境目录env

上述命令执行完成后,就会在Flask_Proj目录下新建一个env目录,并有如下内容:

  1. [hadoop@big01 env]$ ll
  2. total 4
  3. drwxrwxr-x. 2 hadoop hadoop 202 May 17 21:03 bin
  4. drwxrwxr-x. 2 hadoop hadoop 6 May 17 20:53 include
  5. drwxrwxr-x. 3 hadoop hadoop 23 May 17 20:53 lib
  6. lrwxrwxrwx. 1 hadoop hadoop 3 May 17 20:53 lib64 -> lib
  7. -rw-rw-r--. 1 hadoop hadoop 69 May 17 20:53 pyvenv.cfg

然后使用source命令激活bin目录下的activate,就可以激活虚拟环境使用了:

source env/bin/activate

反过来如果想退出虚拟环境,使用deactivate即可。

(2)有了这个env虚拟环境后,在当前工程目录下pip install flask,开启安装flask库。如果默认pypi官方链接速度较慢,可以使用:

pip install -i https://mirrors.aliyun.com/pypi/simple flask

到底是国内镜像,速度不是一般的快。

安装完成后,可以去看一下这个库不是放在python默认安装目录里,而是放在刚创建的虚拟环境目录env里的lib文件夹下,路径为:env/lib/python3.7/site-packages。

flask安装成功后,可以在工程目录下新建一个main.py文件,在其中输入如下内容:

  1. #main.py
  2. from flask import Flask
  3. app = Flask(__name__)
  4. @app.route('/')
  5. def index():
  6. return 'jianhua_helloworld2020'
  7. if __name__ == '__main__':
  8. app.run(port=2021,host='0.0.0.0') #host设置为0.0.0.0,可以允许外部远程访问

然后使用python直接运行这个文件,就可以开启一个测试的web服务:

  1. [hadoop@big01 asmarket]$ python main.py
  2. * Serving Flask app "main" (lazy loading)
  3. * Environment: production
  4. WARNING: This is a development server. Do not use it in a production deployment.
  5. Use a production WSGI server instead.
  6. * Debug mode: off
  7. * Running on http://0.0.0.0:2021/ (Press CTRL+C to quit)

此时可以在外部浏览器上访问这个地址,端口号为2021:

8a03eb1f3c0d23aebefa6e3a4157ce70.png

2. gunicorn部署flask项目

上述在flask工程项目中创建env虚拟环境,是为了保证许多依赖的第三方库版本的一致。如上在启动了flask自带的server后,可以实现外部访问。但这种方式仅适用于测试,无法用于实际部署,因此一般推荐使用gunicorn来搭建flask服务器。

Gunicorn (独角兽)是一个高效的Python WSGI Server,通常用它来运行 wsgi application(由我们自己编写遵循WSGI application的编写规范) 或者 wsgi framework(如Django,Paster),地位相当于Java中的Tomcat。

(1)安装gunicorn

gunicorn是一个第三方库,可以直接使用pip来安装:

pip install -i https://mirrors.aliyun.com/pypi/simple gunicorn

(2)使用gunicorn命令

基本使用方式:

gunicorn --workers=3 main:app 

--workers=3表示三个进程,main:app,其中main为之前flask工程中的main.py,意味这将main.py对象实例化为app。

允许上述命令后,就会出现如下提示:

  1. (env) [hadoop@big01 asmarket]$ gunicorn --workers=4 te:app
  2. [2020-05-17 22:21:04 +0800] [9123] [INFO] Starting gunicorn 20.0.4
  3. [2020-05-17 22:21:04 +0800] [9123] [INFO] Listening at: http://127.0.0.1:8000 (9123)
  4. [2020-05-17 22:21:04 +0800] [9123] [INFO] Using worker: sync
  5. [2020-05-17 22:21:04 +0800] [9126] [INFO] Booting worker with pid: 9126
  6. [2020-05-17 22:21:04 +0800] [9127] [INFO] Booting worker with pid: 9127
  7. [2020-05-17 22:21:05 +0800] [9128] [INFO] Booting worker with pid: 9128
  8. [2020-05-17 22:21:05 +0800] [9129] [INFO] Booting worker with pid: 9129

可以看到上述监听地址为:127.0.0.0,端口为8000。工作模式为sync,即同步工程模式。这两种参数都可以进行修改,其中监听地址和端口号可以在上述命令后添加 -b ip:port方式实现:

gunicorn --workers=3 main:app -b 0.0.0.0:2021

在shell命令窗口:

  1. (env) [hadoop@big01 asmarket]$ gunicorn --workers=4 te:app -b 0.0.0.0:2021
  2. [2020-05-17 22:26:29 +0800] [9162] [INFO] Starting gunicorn 20.0.4
  3. [2020-05-17 22:26:29 +0800] [9162] [INFO] Listening at: http://0.0.0.0:2021 (9162)
  4. [2020-05-17 22:26:29 +0800] [9162] [INFO] Using worker: sync
  5. [2020-05-17 22:26:29 +0800] [9165] [INFO] Booting worker with pid: 9165
  6. [2020-05-17 22:26:29 +0800] [9166] [INFO] Booting worker with pid: 9166
  7. [2020-05-17 22:26:29 +0800] [9167] [INFO] Booting worker with pid: 9167
  8. [2020-05-17 22:26:29 +0800] [9168] [INFO] Booting worker with pid: 9168

此时同样可以在外部浏览器中访问,获得的效果与直接使用flask来搭建server服务一致。

对于工作模式,默认是sync,即同步模式。这种模式就是说在调用的时候,必须等待调用返回结果后,决定后续的行为。而异步则是在调用这个job的时候,不用等待其执行结果,还可以执行其他job。

举个例子:

打电话问酒店晚上有没有房间,如果是同步通信机制,酒店前台会礼貌的说:“请您稍等,我查一下",等她查到结果了就告诉你结果,这个过程中你的电话是一直通着的,在等她的结果,决定住她们家还是去别的酒店。如果是异步通信机制,酒店前台会礼貌的说:”我先查一下,一会给您回过去。“然后她把电话挂了。你马上就可以拿手机看看周边是否有便利的餐馆。等她查到了,她会主动给你打电话。而此时餐馆也查好了,可以开启美好的旅行了。

如果要更换为异步模式,可以使用gevent。此时还需要pip来安装gevent。

gunicorn --workers=3 main:app -b 0.0.0.0:2021 -k 'gevent'

(3)使用参数配置文件设定

使用上述脚本命令还是不方便的,gunicorn可以使用-c参数,就是使用配置文件。将一些参数设定放在该配置文件里:

  1. import os
  2. bind='0.0.0.0:5001' #绑定监听ip和端口号
  3. workers=3 #同时执行的进程数,推荐为当前CPU个数*2+1
  4. backlog=2048 #等待服务客户的数量,最大为2048,即最大挂起的连接数
  5. worker_class="gevent" #sync, gevent,meinheld #工作模式选择,默认为sync,这里设定为gevent异步
  6. max_requests=1000 #默认的最大客户端并发数量
  7. daemon=True # 是否后台运行
  8. reload=True # 当代码有修改时,自动重启workers。适用于开发环境。
  9. pidfile='./gunicore.pid' #设置pid文件的文件名
  10. loglevel='debug' # debug error warning error critical
  11. accesslog='log/gunicorn.log' #设置访问日志
  12. errorlog='log/gunicorn.err.log' #设置问题记录日志

将上述内容存放在config.py文件中,然后在命令行输入:

gunicorn -c config.py main:app

如下为本次实践时配置的config.py参数:

  1. import os
  2. from gevent import monkey
  3. monkey.patch_all()
  4. import multiprocessing
  5. debug = False
  6. bind = "0.0.0.0:5001"
  7. pidfile = "gunicorn.pid"
  8. accesslog="/home/hadoop/asmarket/logs/gunicorn.log"
  9. workers = multiprocessing.cpu_count()*2 + 1
  10. worker_class = "gevent"
  11. daemon=True

然后开启运行,此时gunicorn设置为后台看守进程,先直接从外部浏览器访问,然后查看log文件,内容如下:

  1. [hadoop@big01 logs]$ more gunicorn.log
  2. 192.168.58.1 - - [17/May/2020:23:30:44 +0800] "GET / HTTP/1.1" 200 23 "-" "Mozi
  3. lla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/
  4. 68.0.3440.106 Safari/537.36"
  5. 192.168.58.1 - - [17/May/2020:23:30:46 +0800] "GET / HTTP/1.1" 200 23 "-" "Mozi
  6. lla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/
  7. 68.0.3440.106 Safari/537.36"
  8. 192.168.58.1 - - [17/May/2020:23:30:47 +0800] "GET / HTTP/1.1" 200 23 "-" "Mozi
  9. lla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/
  10. 68.0.3440.106 Safari/537.36"

至此基本的gunicorn+flask异步服务部署就实现了。

3. gunicorn+nginx配置

有了gunicorn和gevent后,gunicorn可以实现多进程http服务,不过其性能还是相对nginx这种专业的web服务要差一些,主要体现在对高并发的处理、安全问题、静态资源文件的处理等。因此一般情况会在gunicorn之上再配置一层nginx服务。其基本架构示意如下(图来源于百度):

968fc90c812c2a62736a03d3e458aa87.png

(1)docker部署nginx

由于nginx采用安装方式还相对比较麻烦,可以直接使用docker来部署。不过当然首先在root账户下安装docker服务:

  1. #yum安装docker
  2. yum install docker
  3. #启动docker进程服务
  4. systemctl start docker
  5. systemctl enable docker

有了docker后,使用docker的search和pull服务就可以将nginx拉取到本机上:

  1. [root@big01 ~]# docker pull nginx
  2. Using default tag: latest
  3. Trying to pull repository docker.io/library/nginx ...
  4. latest: Pulling from docker.io/library/nginx
  5. afb6ec6fdc1c: Pull complete
  6. b90c53a0b692: Pull complete
  7. 11fa52a0fdc0: Pull complete
  8. Digest: sha256:30dfa439718a17baafefadf16c5e7c9d0a1cde97b4fd84f63b69e13513be7097
  9. Status: Downloaded newer image for docker.io/nginx:latest

然后使用docker 查看镜像:

  1. [root@big01 ~]# docker images
  2. REPOSITORY TAG IMAGE ID CREATED SIZE
  3. docker.io/nginx latest 9beeba249f3e 2 days ago 127 MB
  4. docker.io/hello-world latest bf756fb1ae65 4 months ago 13.3 kB

接下来可以运行nginx容器:

  1. [root@big01 ~]# docker run --name mynginx -p 8080:80 -d nginx
  2. 79b2f668784f866869f41ab08468784cf5f694fb451486250f37eaaa11808411

此时可以从外部浏览器访问获得默认的nginx响应页面:

5a806e8d25ab912fb181430af3bc77f2.png

下面对nginx访问页面做一个映射,因为如果要进入docker内部访问的话还是很不方便的,因此一般情况将docker镜像作为一个服务,而将实际的资源进行一个映射。在本地机器上放置资源,映射到容器内部,nginx访问内部文件路径时就映射到访问外部本地资源上了,这样便于资源分配以及web文件的管理。这里就是增加一个docker的-v参数,格式为本地资源:容器资源。

先进入docker内部,查看nginx的配置文件:

  1. [root@big01 nginx]# docker exec -it 16528ae739c4 /bin/bash
  2. root@16528ae739c4:/# cd /etc/nginx/conf.d/
  3. root@16528ae739c4:/etc/nginx/conf.d# more default.conf
  4. server {
  5. listen 80;
  6. server_name localhost;
  7. #charset koi8-r;
  8. #access_log /var/log/nginx/host.access.log main;
  9. location / {
  10. root /usr/share/nginx/html;
  11. index index.html index.htm;
  12. }
  13. #error_page 404 /404.html;
  14. # redirect server error pages to the static page /50x.html
  15. #
  16. error_page 500 502 503 504 /50x.html;
  17. location = /50x.html {
  18. root /usr/share/nginx/html;

默认访问的路径为/usr/share/nginx/html下的html文件,这个可以后续修改。我们可以先测试一下,将这个路径映射到本地机器上。这样需要重新run一个镜像:

  1. [root@big01 nginx]# docker run --name mynginxt -v /usr/share/nginx/:/usr/share/nginx/html -p 8021:80 -d nginx
  2. 16528ae739c40d28a68be67b10aac42343b97b5fa468565127eaf051ea25886c

上述命令中:-v /usr/share/nginx/:/usr/share/nginx/html,就是将本地的/usr/share/nginx目录映射到容器内部的/usr/share/nginx/html目录中,如果我们在本地的nginx目录下新建一个index.html网页,那访问的时候就是访问这个新建的index.html网页。如下新建一个简单网页并保存为index.html。

  1. <html>
  2. <head>
  3. <meta charset="utf-8">
  4. </head>
  5. <body>
  6. <h1>我的第一个标题</h1>
  7. <p>我的第一个段落。</p>
  8. </body>
  9. </html>

接下来就可以在外部浏览器访问,注意端口现在为8021。

3f781fd10a4338368c77c0ff6ae61e00.png

(2)nginx+gunicorn部署

上述gunicorn部署时,ip为0.0.0.0,端口号为5001。在使用nginx代理这个服务时,修改nginx相应的配置文件即可。不过因为是docker部署,因此还需使用docker来操作。此时也可以将配置文件映射到外部宿主机上。

首先启动gunicorn+flask项目服务:

[hadoop@big01 asmarket]$ gunicorn -c config.py main:app

然后在/usr/share/nginx目录下新建一个nginx.conf文件,在其中输入如下内容:

  1. server {
  2. listen 80;
  3. server_name asmarket.com; # 这是HOST机器的外部域名,用地址也行
  4. location / {
  5. proxy_pass http://0.0.0.0:5001; # 这里是指向 gunicorn host 的服务地址
  6. proxy_set_header Host $host;
  7. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  8. }
  9. }

将其映射到nginx容器里的default.conf配置文件:

  1. [root@big01 nginx]# docker run --name mynginx -v /usr/share/nginx/nginx.conf:/etc/nginx/conf.d/default.conf -d nginx
  2. 39026ba7d80eac3d59d00ead25d7275e5f2b125dde3a9e3379dffb5c10ef9662

这样在启动nginx时直接使用的就是刚才新建立的nginx.conf配置文件。

此时nginx已经启动了:

  1. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  2. 39026ba7d80e nginx "nginx -g 'daemon ..." 7 minutes ago Up 7 minutes 80/tcp mynginx

然后就可以运行flask项目了。

如何验证确实是代理了gunicornweb服务,可以直接使用nginx原有的默认80端口访问,如果出现错误,说明nginx已经代理了web服务,否则就是没成功。

(3)supervisor进程守护

nginx一般不会莫名其妙被关闭,但gunicorn是一个进程,完成有有可能因为一些原因被关闭或者阻塞,为了保证gunicorn进程,需要使用看护进程插件。这里使用supervisor来解决这个问题。

supervisor专门用户linux端进程管理,首先使用pip安装一下这个插件:

[root@big01 ~]# pip install supervisor

安装成功后,可以创建一个配置文件:

  1. # 设置默认配置
  2. $ echo_supervisord_conf > /etc/supervisord.conf
  3. $ vi /etc/supervisord.conf

这个配置文件放在/etc/目录下,名为supervisor.conf。接下来就可以修改其配置了:

  1. [program:myapp]
  2. command=/usr/local/bin/gunicorn -c config.py main:app
  3. directory=/home/hadoop/asmarket
  4. autostart=true ; start at supervisord start (default: true)
  5. startsecs=1 ; # of secs prog must stay up to be running (def. 1)
  6. startretries=3 ; max # of serial start failures when starting (default 3)
  7. exitcodes=0 ; 'expected' exit codes used with autorestart (default 0)
  8. stdout_logfile=/home/hadoop/asmarket/logs/main.logs
  9. stdout_logfile_maxbytes=50MB ; max # logfile bytes b4 rotation (default 50MB)
  10. user=root

修改完成后,直接使用supervisord来执行:

supervisord -c supervisor.conf

这样myapp的进程就启动了。可以使用supervisorctl status命令来查看当前进程状态:

supervisorctl status
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/185780
推荐阅读
相关标签
  

闽ICP备14008679号