[Python] flask运行+wsgi切换生产环境+supervisor配置指南
作者:mmseoamin日期:2023-12-25

文章目录

  • 问题背景
  • flask启动
    • 方式1(编写main函数):
    • 方式2(编译器):
    • 方式3(命令行):
    • 方法4(重命名文件法):
    • 方法5(使用flask命令行):
    • 关于WSGI
    • 生产环境
      • 专业wsgi服务器
      • 托管平台
      • 自动化管理
        • yum安装supervisor
        • END

          问题背景

          flask项目本地启动时,控制台会打印如下warning

          WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
          

          在这里插入图片描述

          翻译成 人话就是,“我这个环境就是你开发时用,实际生产的时候可别找我,出事我不负责。”

          好家伙呀。


          但是他指了另外一条路:Use a production WSGI server。

          依然还是带着问题学习,从本篇文章可以了解如下内容

          1. flask本身自带的为啥不能用?
          2. 他推荐的是什么?为什么他能用?
          3. 怎么部署一个wsgi?以及后续怎么用?

          额外知识补充:flask的多种启动方式

          Before we start, 本教程假设你已经有一个flask应用并准备部署了。


          flask启动

          方式1(编写main函数):

          直接在文件里写个main函数然后运行

          if __name__ == '__main__':
              # 本地启动
              # 这里的HOST_IP及SERVER_PORT可以自己设置
              app.run(host=HOST_IP, port=SERVER_PORT, debug=True)
          

          方式2(编译器):

          我用的是pyCharm,可以直接进行配置

          在这里插入图片描述

          按照如下方式进行配置,首先点击左上角加号,分类为Flask server,Additional options为运行的额外参数,需要在变量位置增加FLASK_APP=你的py文件地址。这里的py文件就是你包含了app = Flask(__name__) 这行代码的文件。

          在这里插入图片描述

          启动起来啦

          在这里插入图片描述

          方式3(命令行):

          依然先设置环境变量,在终端中输入(非常关键的是等号旁边不要有空格!)

          set FLASK_APP=D:\Code\ctb_v2\app\controllers\hello.py
          

          检查一下设置成功没有

          在这里插入图片描述

          输入flask run 或python -m flask run运行应用

          在这里插入图片描述

          如果需要指定ip或者端口

          flask run --host=0.0.0.0 --port=9999
          

          方法4(重命名文件法):

          可以把文件命名为app.py或者wsgi.py,再进入到该文件的文件夹,运行flask run启动项目。

          在这里插入图片描述

          方法5(使用flask命令行):

          通过flask --app的命令行进行设置

          在这里插入图片描述

          关于WSGI

          wsgi是啥?全称是Python Web Server Gateway Interface。由此可以看出它是接口,并非一个统称的服务器类型。它提供了web服务器和web应用之间的通用接口,服务器和框架的开发者需要按照WSGI的规则去实现。

          需要注意的是

          Flask应用本身就是一个WSGI应用!

          直接看flask的代码

          # 位于flask\app.py文件
            def __call__(self, environ: dict, start_response: t.Callable) -> t.Any:
                  """The WSGI server calls the Flask application object as the
                  WSGI application. This calls :meth:`wsgi_app`, which can be
                  wrapped to apply middleware.
                  """
                  return self.wsgi_app(environ, start_response)
          

          可以看到它直接Flask app创建时实际是引用了wsgi_app.

          因此回看那条报错,实际上它是说,启动flask的开发wsgi(内置)服务器不稳定,生产环境要用生产的wsgi服务器。

          生产环境

          在生产环境中,可以使用生产wsgi服务器或托管平台来运行flask应用。以下分别进行简单介绍。

          专业wsgi服务器

          1. Gunicorn

          全称令人意想不到:Green Unicorn哈哈哈。

          • 不支持Windows
          • 不需要额外的依赖或编译、易安装
          • 使用方式:gunicorn myproject:app,这就等于python文件中写的 from myproject import app
          • 可设定进程数:gunicorn -w 4 myproject:app 表示要运行4个进程
          • 可开放外部访问:gunicorn -b 0.0.0.0 -w 4 myproject:app
          • 可gevent 或 eventlet 进行异步操作

            2. Waitress

            • 支持windows
            • 不需要额外的依赖或编译、易安装
            • 不支持流式请求
            • 创建一个进程,由进程创建多个线程
            • 使用方式:waitress-serve --host 0.0.0.0 hello:app 等于 ‘from hello import app’
            • 若为工厂方法:waitress-serve --host 127.0.0.1 --call hello:create_app 等于 ‘from hello import create_app’

              3. mod_wsgi

              • 支持windows
              • 与Apache httpd集成
              • 需要编译器和apache开发头文件来安装,可以参考这个文章apache+mod_wsgi+flask部署

                4. uWSGI

                • 不支持Windows
                • 配置复杂
                • 是已编译的服务器套件
                • 支持gevent异步操作

                  托管平台

                  常见的托管平台包括以下,这里不展开了。

                  • PythonAnywhere
                  • Google App Engine
                  • Google Cloud Run
                  • AWS Elastic Beanstalk
                  • Microsoft Azure

                    自动化管理

                    为了方便进程管理,这里使用supervisor来管理我们的服务,例如后台运行,重启,日志输出等等都可以通过supervisor进行控制。

                    可以使用两种方式进行安装,推荐yum(如果系统是centOS) ,通过pip或者agt(Ubuntu)进行安装步骤会多一些。

                    以下介绍yum的安装方式

                    开始之前,先区分几个名词

                    supervisor:要安装的软件的名称。

                    supervisord:装好supervisor软件后,supervisord用于启动supervisor服务。

                    supervisorctl:用于管理supervisor配置文件中program和supervisor服务本身。

                    yum安装supervisor

                    1. 安装

                    #切换为root用户
                    sudo su 
                    yum install epel-release
                    yum install -y supervisor
                    
                    # 开机自启动
                    systemctl enable supervisord 
                    # 启动supervisord服务
                    systemctl start supervisord 
                    
                    # 查看supervisord服务状态
                    systemctl status supervisord 
                    # 查看是否存在supervisord进程
                    ps -ef|grep supervisord 
                    

                    2. 配置

                    访问supervisord的配置文件

                    vim /etc/supervisord.conf 
                    

                    在这里插入图片描述

                    这个文件夹保存的是supervisor管理的服务的配置文件

                    我们去这个文件夹下面创建文件

                    vim /etc/supervisord.d/myprogram.init
                    

                    这里面具体怎么写,可以参考刚刚/etc/supervisord.conf 文件里有提供参考,以下提供一个示例

                    [program:你的服务名]   
                    ; 启动命令 以下为gunicorn的实例,按实际情况来,比如:flask run
                    ; 具体命令参考上面flask启动那一章
                    command=gunicorn pygun.conf wsgi:app --log-level=debug --preload
                    ; 工作目录(脚本启动目录的全路径)
                    directory=/a/b/c
                    ; 进程数
                    numprocs=1
                    ; supervisord尝试启动一个程序时尝试的次数。默认是3
                    startretires=5
                    ; supervisord守护程序启动时自动启动
                    autostart=true    
                    ; supervisord守护程序重启时自动重启     
                    autorestart=true
                    ;将stderr重定向到stdout        
                    redirect_stderr=true   
                    ; 日志标准输出路径,同时脚本print打印信息也会在改文件显示
                    stdout_logfile=./stdout.log
                    stdout_logfile_maxbytes=1MB   ; max # logfile bytes b4 rotation (default 50MB)
                    stdout_logfile_backups=10     ; # of stdout logfile backups (default 10)
                    stderr_logfile=./error.log
                    stderr_logfile_maxbytes=1MB   ; max # logfile bytes b4 rotation (default 50MB)
                    stderr_logfile_backups=10     ; # of stderr logfile backups (default 10)
                    

                    3. 加载配置

                    #读取有更新的配置文件,不会启动新添加的程序
                    supervisorctl reread
                    #重启配置文件修改过的程序
                    supervisorctl update
                    #启动xx程序
                    supervisorctl start 你的服务名
                    #查看所有服务状态
                    supervisorctl status
                    

                    END

                    参考

                    1. flask的官方使用教程:https://flask.palletsprojects.com/en/2.2.x/quickstart/
                    2. flask的官方部署教程:https://flask.palletsprojects.com/en/2.2.x/deploying/
                    3. WSGI官方文档:https://peps.python.org/pep-0333/
                    4. 其他博主的文章:centos7安装supervisor详细教程