CentOS下通过Supervisor管理虚拟环境的Gunicorn Flask项目,实现开机自启等功能

原文 https://www.cyberlight.xyz/passage/supervisor-flask

搭建CyberLight后有了完整Python建站经历,在此做下记录,以便之后查询,希望能帮到初学python建站的朋友。

本次笔记的默认条件为:

1. 您已在Linux成功部署Flask开发环境,欲部署生产环境。

2.此时您已自建Flask项目目录,并安装了虚拟环境。

3.您的域名已解析到服务器ip。【此处服务器是指物理层面的服务器主机,不是用于请求响应的Web服务器】

 

下面是笔记内容

环境: CentOS 7, Python 3.6.8

一、通过gunicorn运行Flask项目

开发环境中,启动Flask常见图中的红色警告,Flask官方并不建议我们将此服务器用于生产环境。在实际生产环境中,我们需要一个性能更强的WSGI服务器,这篇笔记选择了gunicorn。(个人体验后,gunicorn的确比Flask开发时的服务器有肉眼可见的速度提升)

 

下面安装gunicorn

进入Linux终端,命令窗口路径 切换至 项目根目录,首先激活Python虚拟环境

此时,在命令窗口输入

                                        • . venv/bin/activate

                                         

                                        继续输入以下内容,使用pip安装gunicorn

                                                                              • pip3 install gunicorn

                                                                               

                                                                              激活后,输入以下命令运行Flask项目

                                                                                                                    • gunicorn -w 4 -t 30 -b 0.0.0.0:5000 app:app

                                                                                                                     

                                                                                                                    (注意,该命令根据实际情况变化)该命令中,

                                                                                                                    -w后的数字代表worker(工作线程)数量(-w 4代表4个worker进程),通常建议worker数量为 (2 * CPU数量) + 1

                                                                                                                    -t后的数字代表超时时间,单位 秒

                                                                                                                    -b后是 ip:端口(0.0.0.0:5000为在服务器ip下的5000端口运行【此处服务器是指物理层面的服务器主机,不是用于请求响应的Web服务器】)

                                                                                                                    app:app,: 左边的app代表Flask运行的主程序(我的Flask主程序为app.py),: 右边的app照写即可。如,您的Flask主程序名为test.py,则该部分为test:app

                                                                                                                     

                                                                                                                    关于worker数量的选择,在Python环境中,可通过如下代码查询CPU数量


                                                                                                                    import multiprocessing
                                                                                                                    print(multiprocessing.cpu_count())

                                                                                                                    如,我的笔记本处理器,i7-8750H CPU数量为

                                                                                                                    可得,我的笔记本理论能设置 (2 * 12) + 1 = 25 个worker进程。事实上,4~12个worker进程就可以每秒处理成百上千个请求(这段出自李辉大神的《Flask Web 开发实战》,推荐~)

                                                                                                                     

                                                                                                                    启动gunicorn后,便能通过 http://ip:您设置的端口号 进入您的网站了。然而,由于是生产环境的配置,我们往往希望Flask项目能一直运行于后台,而不会关闭命令窗口后失效。

                                                                                                                    我的解决方案是,创建一个专属gunicorn运行的Linux窗口,即便我们退出Linux命令窗口也不影响

                                                                                                                    具体步骤为,

                                                                                                                    停止前面运行的gunicorn,进入Linux(本文是CentOS)命令窗口,输入如下命令安装screen

                                                                                                                                                          • yum install screen

                                                                                                                                                           

                                                                                                                                                          创建一个名为name的新窗口(name为您定义的窗口名【可自由设置】,S一定要大写)

                                                                                                                                                                                                    • screen -S name

                                                                                                                                                                                                     

                                                                                                                                                                                                    进入Flask项目根目录,激活虚拟环境

                                                                                                                                                                                                                                          • . venv/bin/activate

                                                                                                                                                                                                                                           

                                                                                                                                                                                                                                          像之前一样运行gunicorn,如我的命令为

                                                                                                                                                                                                                                                                                • gunicorn -w 4 -t 30 -b 0.0.0.0:5000 app:app

                                                                                                                                                                                                                                                                                 

                                                                                                                                                                                                                                                                                之后按CTRL+A+D离开该窗口(只要不关闭服务器,gunicorn会一直在后台运行)。输入screen -r name能切换回该命令窗口

                                                                                                                                                                                                                                                                                screen的更多命令见这篇笔记https://www.cyberlight.xyz/passage/linux-screen

                                                                                                                                                                                                                                                                                 

                                                                                                                                                                                                                                                                                此处通过 新建独立命令窗口 的方法运行gunicorn,若您需要实现 gunicorn随服务器开机自启(通过supervisor管理gunicorn),别急,笔记末尾将指示。

                                                                                                                                                                                                                                                                                 

                                                                                                                                                                                                                                                                                至此,gunicorn 的配置完成。(此处没有配置80或443端口,将在后面说明)

                                                                                                                                                                                                                                                                                 

                                                                                                                                                                                                                                                                                二、配置Nginx反向代理gunicorn

                                                                                                                                                                                                                                                                                通过VPN技术可以让远程服务器代理客户端,让我们以远程服务器的ip 请求访问 公司的内网,这种代理称为正向代理。Nginx可以作为服务器,代理gunicorn服务端监听来自外部的请求,便是反向代理。我们将用Nginx配置80或443端口反向代理gunicorn的运行端口

                                                                                                                                                                                                                                                                                Nginx是成熟的Web服务器,使用Nginx反向代理gunicorn,不仅能提升程序的处理能力、静态文件的处理效率,还能提高服务器的安全系数,避免直接暴露WSGI服务器。

                                                                                                                                                                                                                                                                                 

                                                                                                                                                                                                                                                                                我通过宝塔面板配置的Nginx和网站数据库,您也可以直接在终端配置,下面是我的方法

                                                                                                                                                                                                                                                                                首先按宝塔的官方教程安装宝塔面板,CentOS输入如下命令(安装前需要确保是干净的操作系统,没有安装过其它环境带的Apache/Nginx/php/MySQL(已有环境不可安装)

                                                                                                                                                                                                                                                                                                                      • yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh

                                                                                                                                                                                                                                                                                                                       

                                                                                                                                                                                                                                                                                                                      安装后,命令窗口会生成登录地址、账号、密码,在浏览器打开并登录即可

                                                                                                                                                                                                                                                                                                                      进入宝塔面板主页面,忽略 首次进入时 推荐的安装提示,选择左侧栏的 软件商店,然后选择 运行环境,安装Nginx

                                                                                                                                                                                                                                                                                                                      安装后,点击Nginx行最右边的设置按钮,选择配置修改(这里便是Nginx的主配置文件)

                                                                                                                                                                                                                                                                                                                      在下面增加一段server配置内容


                                                                                                                                                                                                                                                                                                                      server {
                                                                                                                                                                                                                                                                                                                      listen 80; #监听的端口号,http默认为80,请勿修改
                                                                                                                                                                                                                                                                                                                      server_name www.xxx.com; #这里是您的域名
                                                                                                                                                                                                                                                                                                                          location / {
                                                                                                                                                                                                                                                                                                                              proxy_pass http://0.0.0.0:5000; #这是上面我设置的Nginx运行端口5000,您根据自己的配置设置
                                                                                                                                                                                                                                                                                                                              proxy_redirect off;
                                                                                                                                                                                                                                                                                                                              proxy_set_header Host $host;
                                                                                                                                                                                                                                                                                                                              proxy_set_header X-Real-IP $remote_addr;
                                                                                                                                                                                                                                                                                                                              proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                                                                                                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                                                                                          #用Nginx访问Flask静态文件 #静态文件在static的子目录或更低层的子目录中
                                                                                                                                                                                                                                                                                                                          location /static/(.*) {
                                                                                                                                                                                                                                                                                                                              root /www/flask/xxx/; #这里的路径是绝对路径,xxx是指static目录的上级目录,一般是网站根目录
                                                                                                                                                                                                                                                                                                                          }    
                                                                                                                                                                                                                                                                                                                      }

                                                                                                                                                                                                                                                                                                                      上面的配置中,我的网站绝对路径是 /www/flask/xxx,static目录的路径是/www/flask/xxx/static

                                                                                                                                                                                                                                                                                                                       

                                                                                                                                                                                                                                                                                                                      设置完成后点击保存,点击该窗口(Nginx管理)第一行的 服务,点击 重载配置

                                                                                                                                                                                                                                                                                                                      进入网页,输入 http://+您的域名 变能通过80端口访问网站了,至此,如果没别的需求,网站便能正常运行了

                                                                                                                                                                                                                                                                                                                       

                                                                                                                                                                                                                                                                                                                      下面记录设置https的过程

                                                                                                                                                                                                                                                                                                                      我使用的宝塔免费证书,地址 https://www.bt.cn/admin/safe

                                                                                                                                                                                                                                                                                                                       

                                                                                                                                                                                                                                                                                                                      进入该网站,选择SSL管理,点击申请证书(验证方式选择DNS验证),之后按宝塔的教程验证即可

                                                                                                                                                                                                                                                                                                                      验证成功后下载证书,解压后进入 证书目录/Nginx,将两个文件都传至服务器

                                                                                                                                                                                                                                                                                                                       

                                                                                                                                                                                                                                                                                                                      再次打开宝塔面板的Nginx设置,选择配置修改,和笔记前文一样,插入一段server配置,如下(如果前面插入过80端口的配置,请将80端口的配置删除)


                                                                                                                                                                                                                                                                                                                      server {
                                                                                                                                                                                                                                                                                                                          listen       443 ssl; #监听的端口号,https默认为443,请勿修改
                                                                                                                                                                                                                                                                                                                          server_name  www.xxx.com; #这里是您的域名
                                                                                                                                                                                                                                                                                                                          #下面是证书配置
                                                                                                                                                                                                                                                                                                                          ssl_certificate     /abc/ssl/xxx.pem; #配置证书位置(该路径为服务器存放证书的绝对路径),文件格式为.pem,有时是.srt
                                                                                                                                                                                                                                                                                                                          ssl_certificate_key /abc/ssl/xxx.key; #配置秘钥位置(该路径为服务器存放证书的绝对路径),文件格式为.key
                                                                                                                                                                                                                                                                                                                          #ssl_client_certificate ca.crt;#双向认证
                                                                                                                                                                                                                                                                                                                          #ssl_verify_client on; #双向认证
                                                                                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                                                                      

                                                                                                                                                                                                                                                                                                                      ssl_session_cache    shared:SSL:1m;
                                                                                                                                                                                                                                                                                                                          ssl_session_timeout  5m;
                                                                                                                                                                                                                                                                                                                          ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;
                                                                                                                                                                                                                                                                                                                          ssl_ciphers EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:HIGH:!RC4:!MD5:!aNULL:!eNULL:!NULL:!DH:!EDH:!EXP:+MEDIUM;

                                                                                                                                                                                                                                                                                                                      #上面是证书配置
                                                                                                                                                                                                                                                                                                                          location / {
                                                                                                                                                                                                                                                                                                                              proxy_pass http://0.0.0.0:5000; #这是上面我设置的Nginx运行端口5000,您根据自己的配置设置
                                                                                                                                                                                                                                                                                                                              proxy_redirect off;
                                                                                                                                                                                                                                                                                                                              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_set_header X-Forwarded-Proto $scheme; # fix flask redirect生产环境 从https到http跳转
                                                                                                                                                                                                                                                                                                                          }

                                                                                                                                                                                                                                                                                                                      #用Nginx访问Flask静态文件 #静态文件在static的子目录或更低层的子目录中
                                                                                                                                                                                                                                                                                                                          location /static/(.*) {
                                                                                                                                                                                                                                                                                                                              root /www/flask/xxx/; #这里的路径是绝对路径,xxx是指static目录的上级目录,一般是网站根目录
                                                                                                                                                                                                                                                                                                                          }    
                                                                                                                                                                                                                                                                                                                      }


                                                                                                                                                                                                                                                                                                                      按图中的说明配置证书即可,静态文件的配置方法和笔记上文提到的一样

                                                                                                                                                                                                                                                                                                                       

                                                                                                                                                                                                                                                                                                                      如果需要:当客户访问http时,自动跳转到https。 则再插入一段server配置


                                                                                                                                                                                                                                                                                                                      server {
                                                                                                                                                                                                                                                                                                                          listen 80; #监听80端口
                                                                                                                                                                                                                                                                                                                          server_name www.xxx.com; #这里是域名
                                                                                                                                                                                                                                                                                                                          rewrite ^(.*)$ https://$host$1 permanent; #将http请求强制跳转到https
                                                                                                                                                                                                                                                                                                                      }

                                                                                                                                                                                                                                                                                                                      同样,保存后重载Nginx配置。

                                                                                                                                                                                                                                                                                                                      以上是Flask部署https的全部设置,现在便能通过 https://您的域名 访问您的网站了

                                                                                                                                                                                                                                                                                                                       

                                                                                                                                                                                                                                                                                                                      三、配置Nginx访客日志

                                                                                                                                                                                                                                                                                                                      由于通过Nginx反向代理gunicorn,我们可以直接通过Nginx统计访客,生成访客日志,有了日志,便能用Python数据分析访客情况

                                                                                                                                                                                                                                                                                                                      和笔记前文一样,进入Nginx的 设置—配置修改 中,在已存在的http{}配置中增加如下内容,增加后的大致结构如下


                                                                                                                                                                                                                                                                                                                      http
                                                                                                                                                                                                                                                                                                                      

                                                                                                                                                                                                                                                                                                                      {
                                                                                                                                                                                                                                                                                                                            log_format main '$remote_addr - r e m o t e u s e r [ remote_user [ remoteuser[time_iso8601] “ r e q u e s t " ′         ′ request" '        ' request"    status b o d y b y t e s s e n t " body_bytes_sent " bodybytessent"http_referer” ’
                                                                                                                                                                                                                                                                                                                             ‘“ h t t p u s e r a g e n t " " http_user_agent" " httpuseragent""http_x_forwarded_for”’;

                                                                                                                                                                                                                                                                                                                      access_log  logs/access.log  main; #访客日志的生成路径,这是相对路径,它的根目录是Nginx的安装目录

                                                                                                                                                                                                                                                                                                                      …   #…代表http作用域中原来的内容,不必关心,保持不变即可,只需要添加上面的内容

                                                                                                                                                                                                                                                                                                                      }


                                                                                                                                                                                                                                                                                                                      Nginx日志的参数分别代表下面的信息

                                                                                                                                                                                                                                                                                                                      参数明细表

                                                                                                                                                                                                                                                                                                                      $remote_addr

                                                                                                                                                                                                                                                                                                                      客户端的ip地址(代理服务器,显示代理服务ip)

                                                                                                                                                                                                                                                                                                                      $remote_user

                                                                                                                                                                                                                                                                                                                      用于记录远程客户端的用户名称(一般为“-”)

                                                                                                                                                                                                                                                                                                                      $time_local

                                                                                                                                                                                                                                                                                                                      用于记录访问时间和时区(这里采用了一种更通用的时间格式,time_iso8601)

                                                                                                                                                                                                                                                                                                                      $request

                                                                                                                                                                                                                                                                                                                      用于记录请求的url以及请求方法

                                                                                                                                                                                                                                                                                                                      $status

                                                                                                                                                                                                                                                                                                                      响应状态码,例如:200成功、404页面找不到等。

                                                                                                                                                                                                                                                                                                                      $body_bytes_sent

                                                                                                                                                                                                                                                                                                                      给客户端发送的文件主体内容字节数

                                                                                                                                                                                                                                                                                                                      $http_user_agent

                                                                                                                                                                                                                                                                                                                      用户所使用的代理(一般为浏览器)

                                                                                                                                                                                                                                                                                                                      $http_x_forwarded_for

                                                                                                                                                                                                                                                                                                                      可以记录客户端IP,通过代理服务器来记录客户端的ip地址

                                                                                                                                                                                                                                                                                                                      $http_referer

                                                                                                                                                                                                                                                                                                                      可以记录用户是从哪个链接访问过来的

                                                                                                                                                                                                                                                                                                                       

                                                                                                                                                                                                                                                                                                                       

                                                                                                                                                                                                                                                                                                                       

                                                                                                                                                                                                                                                                                                                      如下图所示,可以直接进入Nginx根目录,找到日志所在目录

                                                                                                                                                                                                                                                                                                                       

                                                                                                                                                                                                                                                                                                                      之后可以用python进行数据分析,如果我有较好的方案,也会继续做相关笔记

                                                                                                                                                                                                                                                                                                                      感谢您阅读到这里,如果您有任何疑问或其他方法,欢迎到评论区留言哦!

                                                                                                                                                                                                                                                                                                                       

                                                                                                                                                                                                                                                                                                                      注:

                                                                                                                                                                                                                                                                                                                      上述笔记实现了 Gunicorn后台运行,而更多时候我们需要 Gunicorn 随服务器开机自启 或 系统出错时及时重启,我在 CentOS下通过Supervisor管理虚拟环境的Gunicorn Flask项目,实现开机自启等功能 中记录了自己的实现过程,感谢阅读!

                                                                                                                                                                                                                                                                                                                      • 1
                                                                                                                                                                                                                                                                                                                        点赞
                                                                                                                                                                                                                                                                                                                      • 1
                                                                                                                                                                                                                                                                                                                        收藏
                                                                                                                                                                                                                                                                                                                        觉得还不错? 一键收藏
                                                                                                                                                                                                                                                                                                                      • 1
                                                                                                                                                                                                                                                                                                                        评论
                                                                                                                                                                                                                                                                                                                      CentOS中设置Supervisor开机可以按照以下步骤进行操作: 1. 打开Supervisor动脚本文件: ```shell vim /etc/init.d/supervisord ``` 2. 在脚本文件中添加以下内容: ```shell #!/bin/bash # # supervisord Startup script for the Supervisor process control system # # chkconfig: - 64 36 # description: Supervisor is a client/server system to control \ # all processes on the local machine. # processname: supervisord # Source function library . /etc/rc.d/init.d/functions # Path to the supervisorctl script, server binary, # and short-form for messages. supervisorctl=/usr/local/bin/supervisorctl supervisord=${SUPERVISORD-/usr/local/bin/supervisord} prog=supervisord pidfile=${PIDFILE-/var/run/supervisord.pid} lockfile=${LOCKFILE-/var/lock/subsys/supervisord} STOP_TIMEOUT=${STOP_TIMEOUT-60} OPTIONS="${OPTIONS--c /etc/supervisord.conf}" RETVAL=0 start() { echo -n $"Starting $prog: " daemon --pidfile=${pidfile} $supervisord $OPTIONS RETVAL=$? echo [ $RETVAL -eq 0 ] && touch ${lockfile} return $RETVAL } stop() { echo -n $"Stopping $prog: " killproc -p ${pidfile} -d ${STOP_TIMEOUT} $supervisord RETVAL=$? echo [ $RETVAL -eq 0 ] && rm -rf ${lockfile} ${pidfile} } reload() { echo -n $"Reloading $prog: " LSB=1 killproc -p $pidfile $supervisord -HUP RETVAL=$? echo } restart() { stop start } case "$1" in start) start ;; stop) stop ;; status) status -p ${pidfile} $supervisord RETVAL=$? [ $RETVAL -eq 0 ] && echo || echo -n " not" ;; restart) restart ;; condrestart|try-restart) if status -p ${pidfile} $supervisord >&/dev/null; then stop start fi ;; force-reload|reload) reload ;; *) echo $"Usage: $prog {start|stop|restart|condrestart|try-restart|force-reload|reload}" RETVAL=2 esac exit $RETVAL ``` 3. 保存并退出文件。 4. 设置脚本文件的执行权限: ```shell chmod +x /etc/init.d/supervisord ``` 5. Supervisor开机: ```shell systemctl enable supervisord ``` 6. 验证Supervisor是否已经配置为开机: ```shell systemctl is-enabled supervisord ``` 如果输出结果为"enabled",则表示Supervisor已成功配置为开机
                                                                                                                                                                                                                                                                                                                      评论 1
                                                                                                                                                                                                                                                                                                                      添加红包

                                                                                                                                                                                                                                                                                                                      请填写红包祝福语或标题

                                                                                                                                                                                                                                                                                                                      红包个数最小为10个

                                                                                                                                                                                                                                                                                                                      红包金额最低5元

                                                                                                                                                                                                                                                                                                                      当前余额3.43前往充值 >
                                                                                                                                                                                                                                                                                                                      需支付:10.00
                                                                                                                                                                                                                                                                                                                      成就一亿技术人!
                                                                                                                                                                                                                                                                                                                      领取后你会自动成为博主和红包主的粉丝 规则
                                                                                                                                                                                                                                                                                                                      hope_wisdom
                                                                                                                                                                                                                                                                                                                      发出的红包
                                                                                                                                                                                                                                                                                                                      实付
                                                                                                                                                                                                                                                                                                                      使用余额支付
                                                                                                                                                                                                                                                                                                                      点击重新获取
                                                                                                                                                                                                                                                                                                                      扫码支付
                                                                                                                                                                                                                                                                                                                      钱包余额 0

                                                                                                                                                                                                                                                                                                                      抵扣说明:

                                                                                                                                                                                                                                                                                                                      1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
                                                                                                                                                                                                                                                                                                                      2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

                                                                                                                                                                                                                                                                                                                      余额充值