【自动化运维新手村】Flask部署上线

【摘要】

在自动化运维新手村中,我们已经依次讲解了Python的基础知识,函数与面向对象设计,使用了Flask框架作为Web应用的后端,与此同时还学习了数据库的相关知识,最终完成了一个以Flask为后端的资产管理服务。

到目前为止,如果大家可以充分理解并灵活应用所讲的知识点,就已经可以按照自己的实际需求,做出一些基本的运维工具,但如果需要对外提供运维能力,还需要最后一步,那就是将Flask后端部署上线。

【Flask启动】

在讲解Flask框架的第一章节提到,启动Flask可以直接运行如下代码:

if __name__ == "__main__":
    app.run()

但启动之后的日志中会包含如下提示:

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

   Use a production WSGI server instead.

翻译过来的含义就是,当前使用的是开发模式下的服务器,请不要在生产环境使用它,而是要使用一个生成环境下的WSGI服务器

那到底什么是开发模式服务器,什么又是生产环境的WSGI服务器呢?

Web服务的组成

准确来说,一个Flask后端应用,并不等同于一个完整的Web服务,一个完整的Web服务如下图所示:

【自动化运维新手村】Flask部署上线

需要由一个Web服务器接收浏览器发出的HTTP请求,并经由WSGI标准接口与APP进行通信,APP处理完请求之后,再将响应经由WSGI处理,最终由Web服务器发送给前端。

Flask应用就是APP的角色,而Server通常会由另一个组件来实现,当通过 app.run()启动Flask应用时,其实是Flask内置了一个仅用于开发调试的低性能、简易的Server,这也是为什么不建议直接在生产环境使用 app.run()来部署Flask应用(不建议并不是不能)。

; WSGI

那什么又是WSGI呢?

百度百科定义如下:
Web服务器网关接口(Python Web Server Gateway Interface,缩写为WSGI)是为Python语言定义的Web服务器和Web应用程序或框架之间的一种简单而通用的接口。

上文提到,Server需要由单独的组件来充当,那么Server在与APP交互过程中,就需要遵循一种规范,这个规范就是WSGI。

更为通俗的讲,充当WebServer角色的可以有很多组件;也有很多框架可以充当WebApp的角色,但只要它们双方都遵守WSGI规范,那么编程人员就可以用任意一个WebServer组件去和任意一种WebApp对接。

WSGI区分为两个部分:一为”服务器”或”网关”,另一为”应用程序”或”应用框架”。在处理一个WSGI请求时,服务器会为应用程序提供环境信息及一个回调函数(Callback Function)。当应用程序完成处理请求后,透过前述的回调函数,将结果回传给服务器。

所谓的 _WSGI中间件_同时实现了API的两方,因此可以在WSGI服务器和WSGI应用之间起调解作用:从Web服务器的角度来说,中间件扮演应用程序,而从应用程序的角度来说,中间件扮演服务器。”中间件”组件可以执行以下功能:

1.重写环境变量后,根据目标URL,将请求消息路由到不同的应用对象。

2.允许在一个进程中同时运行多个应用程序或应用框架。

3.负载均衡和远程处理,通过在网络上转发请求和响应消息。

4.进行内容后处理。

Flask作为应用程序,它适配实现WSGI规范的源代码大致如下:

def wsgi_app(self, environ: dict, start_response: t.Callable) -> t.Any:
    ctx = self.request_context(environ)
    error: t.Optional[BaseException] = None
    try:
        try:
            ctx.push()
            response = self.full_dispatch_request()
        except Exception as e:
            error = e
            response = self.handle_exception(e)
        except:
            error = sys.exc_info()[1]
            raise
        return response(environ, start_response)
    finally:
        if self.should_ignore_error(error):
            error = None
        ctx.auto_pop(error)

这一章节暂时不对源码做深入解读,Flask源码会在后续的Flask进阶内容中进行讲解,感兴趣的读者可以先自行了解。

服务器/网关

目前能够充当Python HTTPServer角色的组件有很多,这一章节主要讲解Gunicorn,该服务器与各种Web框架兼容,实现非常简单,轻量级的资源消耗。可以直接用命令启动,不需要编写配置文件,相对其他的HTTP服务器要简单不少。

【Gunicorn + Flask部署】

部署过程均在Linux环境下进行

安装

Collecting gunicorn
  Downloading gunicorn-20.1.0-py3-none-any.whl (79 kB)
     |████████████████████████████████| 79 kB 539 kB/s
Requirement already satisfied: setuptools>=3.0 in ./venv/lib/python3.8/site-packages (from gunicorn) (59.7.0)
Installing collected packages: gunicorn
Successfully installed gunicorn-20.1.0

如果安装较慢可以加上清华源的后缀 -i https://pypi.tuna.tsinghua.edu.cn/simple

全局配置

安装完gunicorn后无法直接通过命令行执行其二进制文件,如下:


-bash: gunicorn: command not found

因为安装完成后gunicorn可执行文件会存在于python的bin/文件夹下,如果是使用的系统Python环境,则通常会存在于 /usr/local/python3/bin/gunicorn,如果是使用的Python的虚拟环境,则通常会存在于虚拟环境目录 ./venv/bin/gunicorn。需要通过软链接将其链接到 /usr/bin目录下,如下:

设置完成后,执行如下命令确认:


gunicorn (version 20.1.0)
启动Flask应用

将已经完成的Flask上传到Linux环境的机器下;

先执行 python app.py启动Flask应用,然后执行 curl 127.0.0.1:5000/get确认应用程序可以正常运行;

执行 gunicorn app:app,通过gunicorn启动Flask应用,默认会监听 127.0.0.1:8000,输出如下:

[2022-03-27 15:53:53 +0800] [76948] [INFO] Starting gunicorn 20.1.0
[2022-03-27 15:53:53 +0800] [76948] [INFO] Listening at: http://127.0.0.1:8000 (76948)
[2022-03-27 15:53:53 +0800] [76948] [INFO] Using worker: sync
[2022-03-27 15:53:53 +0800] [76954] [INFO] Booting worker with pid: 76954
[2022-03-27 15:53:55 +0800] [76948] [INFO] Handling signal: int
[2022-03-27 15:53:55 +0800] [76954] [INFO] Worker exiting (pid: 76954)
[2022-03-27 15:53:55 +0800] [76948] [INFO] Shutting down: Master

这时再次执行 curl 127.0.0.1:8000/get确认应用可以正常访问

基本配置

gunicorn可以配置一些额外参数,格式如下:

gunicorn -w 进程数量 -b 监听地址:监听端口 运行文件名称:Flask程序实例名

例如:

gunicorn -w 4 -b 0.0.0.0:8080 app:app -D

-D表示将gunicorn置于后台运行

执行 ps -ef | grep gunicorn可以查看gunicorn进程信息


  501 79794     1   0  3:58PM ??         0:00.04  PycharmProjects/flaskProject2/venv/bin/gunicorn -w 4 -b 0.0.0.0:8080 openapi:app -D
  501 79806 79794   0  3:58PM ??         0:00.51 PycharmProjects/flaskProject2/venv/bin/gunicorn -w 4 -b 0.0.0.0:8080 openapi:app -D
  501 79808 79794   0  3:58PM ??         0:00.51 PycharmProjects/flaskProject2/venv/bin/gunicorn -w 4 -b 0.0.0.0:8080 openapi:app -D
  501 79809 79794   0  3:58PM ??         0:00.50 PycharmProjects/flaskProject2/venv/bin/gunicorn -w 4 -b 0.0.0.0:8080 openapi:app -D
  501 79810 79794   0  3:58PM ??         0:00.50 PycharmProjects/flaskProject2/venv/bin/gunicorn -w 4 -b 0.0.0.0:8080 openapi:app -D

除此之外如果生产环境,必不可少还需要配置日志信息,如下:

gunicorn -w 4 -b 0.0.0.0:8080 --access-logfile access.log --error-logfile error.log app:app -D

可以通过 tail -f access.log或者 tail -f error.log查看记录的日志信息。

通用配置

执行 pip install gevent安装依赖包。

gunicorn可以通过执行配置文件来完成启动,配置文件如下


import logging
import logging.handlers
import os
import multiprocessing
import gevent.monkey
gevent.monkey.patch_all()

bind = '0.0.0.0:8080'
chdir = '/home/flaskProject'
timeout = 60
worker_class = 'gevent'
workers = multiprocessing.cpu_count() * 2 + 1
loglevel = "info"
access_log_format = '%(t)s %(p)s %(h)s "%(r)s" %(s)s %(L)s %(b)s %(f)s" "%(a)s"'
pidfile = "gunicorn.pid"
accesslog = "access.log"
errorlog = "error.log"
daemon = True

执行 gunicorn -c gun.py app:app启动应用程序,

启动后项目的目录下会生成 access.logerror.loggunicorn.pid三个文件, gunicorn.pid中保存了gunicorn的主进程PID号,可以通过 cat gunicorn.pid查看,当想要停止gunicorn时,直接 kill 进程号即可杀死所有gunicorn进程。

【总结】

单纯的Flask 自带的Web服务器做下测试,在压力大的时候出现socket的问题,因为他是单进程单线程的。而使用gunicorn来启动,响应速度和能力提升显著。
配置中workers指定启动的进程数。cpu的损耗是平均到各个进程。workers的值一定不要过大,毕竟多进程对于系统的调度消耗比较大。

这一章节的结束,就标志着自动化运维新手村系列正式完结了,希望大家可以通过这一系列的学习,都可以快速上手Python,并结合自己的场景完成特定的自动化运维小工具,敬请期待自动化运维初级村的更多内容。

欢迎大家添加我的个人公众号【Python玩转自动化运维】加入读者交流群,获取更多干货内容

Original: https://blog.csdn.net/weixin_40489165/article/details/123776458
Author: EthanYue1024
Title: 【自动化运维新手村】Flask部署上线

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/746144/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球