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

本文介绍了如何在自动化运维中部署Flask应用,包括Web服务的组成、WSGI概念、Gunicorn服务器的安装与配置,以及Flask应用的启动与基本配置。通过Gunicorn,可以提高Flask应用在生产环境的稳定性和性能。
摘要由CSDN通过智能技术生成

【摘要】

在自动化运维新手村中,我们已经依次讲解了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服务如下图所示:

在这里插入图片描述

需要由一个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环境下进行

安装
# pip install gunicorn
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后无法直接通过命令行执行其二进制文件,如下:

# gunicorn -h
-bash: gunicorn: command not found

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

# ln -s /usr/local/python/bin/gunicorn /usr/bin/gunicorn

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

# gunicorn -v
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进程信息

# ps -ef | grep 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可以通过执行配置文件来完成启动,配置文件如下

# gun.py
import logging
import logging.handlers
import os
import multiprocessing
import gevent.monkey
gevent.monkey.patch_all()

bind = '0.0.0.0:8080'  # 绑定的ip已经端口号
chdir = '/home/flaskProject'  # gunicorn要切换到的目的工作目录
timeout = 60  # 超时
worker_class = 'gevent'  # 使用gevent模式,还可以使用sync 模式,默认的是sync模式
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"'  # 设置gunicorn访问日志格式,错误日志无法设置
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玩转自动化运维】加入读者交流群,获取更多干货内容

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值