python-39-flask+nginx+Gunicorn的组合应用

flask + nginx + Gunicorn = 王炸

1 flask+nginx+gunicorn+supervisor

1.1 myapp.py

from flask import Flask
app = Flask(__name__)@app.route("/")
def test_link():return "the link is very good"if __name__=="__main__":app.run()

默认是5000端口。
打开虚拟机pip install flask
运行代码python3 myapp.py
访问 curl http://127.0.0.1:5000

1.2 Gunicorn

WSGI (Web Server Gateway Interface) 是 Python 应用程序与 Web 服务器之间的标准接口。Gunicorn 和 uWSGI 是两个常用的 WSGI 服务器。
(1)安装pip install gunicorn。
安装sudo apt install gunicorn。
安装后的路径:/usr/bin/gunicorn。
(2)可以使用Gunicorn来运行Flask应用。 此时Flask应用的入口文件是 myapp.py,可以使用以下命令来运行它:

默认分配给flask应用一个端口8000
gunicorn --workers=2 myapp:app  也可以使用-b参数显式指定
gunicorn --workers=2 -b 0.0.0.0:5000 myapp:app

在这个命令中,workers=2表示使用2个工作进程,myapp:app表示Flask应用的入口文件是myapp.py,并且Flask应用的实例名是app。

在生产环境中,我们通常会使用进程管理工具(如Supervisor或systemd)来保证Gunicorn服务器的持续运行。

1.3 Supervisor

(1)安装sudo apt install supervisor。
(2)然后需要创建一个配置文件来告诉Supervisor如何运行你的Gunicorn服务器。

[program:myapp]
directory=/home/zb/mydir
command=/usr/bin/gunicorn -w 2 myapp:app
autostart=true
autorestart=true
stderr_logfile=/var/log/myapp.err.log
stdout_logfile=/var/log/myapp.out.log
user=zb

在这个配置中,directory是你的应用程序的目录,command是运行你的Gunicorn服务器的命令,user是运行服务器的用户。
(3)保存并关闭文件,然后使用以下命令来更新Supervisor的配置:

sudo supervisorctl reread
sudo supervisorctl update

此时已经生效了。

(4)最后可以使用以下命令来启动你的应用程序:

sudo supervisorctl start myapp
sudo supervisorctl stop myapp

现在,你的Gunicorn服务器应该会一直运行,即使你的服务器重启。

注意:在生产环境中,可能需要使用Nginx或Apache等Web服务器来代理你的Flask应用。

1.4 Nginx

要在Flask应用程序前使用Nginx作为反向代理,你需要进行以下步骤:
(1)安装sudo apt-get install nginx
(2)配置Nginx
sudo vi /etc/nginx/sites-available/default

server {listen 80;location / {proxy_pass http://localhost:8000;}
}

在这个配置中,Nginx会监听80端口,并将所有请求转发到本地的8000端口(你的gunicorn启动的Flask应用)。
(3)启动或重启Nginx

sudo systemctl restart nginx

此时curl http://127.0.0.1:8000/
或者curl http://127.0.0.1/都可以。

2 flask中的日志模块

Python Flask + Gunicorn + Docker 的日志输出设置
flask学习之日志logging

2.1 缺省配置(普通Flask日志设置)

Flask本身使用Python的logging模块来实现日志记录、输出。

Flask中也有自己的日志模块,通过flask的实例(一般叫作app)能够直接调用日志模块,输出或者记录日志。
(1)主程序main.py

import logging
from flask import Flask, jsonify
from flask import current_app
from children import task
app = Flask(__name__)@app.route('/')
def default_route():"""Default route"""app.logger.debug('this is a DEBUG message')app.logger.info('this is an INFO message')app.logger.warning('this is a WARNING message')app.logger.error('this is an ERROR message')app.logger.critical('this is a CRITICAL message')task()return jsonify('hello world')@app.route('/current_app')
def default_route_current_app():current_app.logger.debug('this is a DEBUG message current app')task()return jsonify('hello world current app')if __name__ == '__main__':app.run(host='0.0.0.0', port=8000, debug=True)

(2)子程序children.py

from flask import current_app
def task():current_app.logger.info("I am children")

有一个问题就是在蓝图中如何使用flask的日志模块呢?还记得flask中的current_app吗,这个current_app返回的就是该蓝图注册所在的flask实例。在flask中的蓝图要使用app(flask的实例)中的一些方法或者属性就需要用到current_app。
在这里插入图片描述

我们是在flask应用实例创建之后在添加的handler,因此,在flask应用实例创建的时候已经使用了缺省配置,添加了一个StreamHandler到app.logger了。

2.2 输出到文件方式一

可以使用 logging 模块的不同输出处理器(Handler)来实现标准输出、文件输出或邮件提醒。例如添加日志文件:

import logging
from flask import Flask, jsonify
from flask import current_app
from children import task
app = Flask(__name__)@app.route('/')
def default_route():"""Default route"""app.logger.debug('this is a DEBUG message')app.logger.info('this is an INFO message')app.logger.warning('this is a WARNING message')app.logger.error('this is an ERROR message')app.logger.critical('this is a CRITICAL message')task()return jsonify('hello world')@app.route('/current_app')
def default_route_current_app():current_app.logger.debug('this is a DEBUG message current app')task()return jsonify('hello world current app')if __name__ == '__main__':print(app.debug)  # 默认为Falseapp.debug = Truehandler = logging.FileHandler('flask.log')app.logger.addHandler(handler)app.run(host='0.0.0.0', port=8000)

可以看到在当前目录下生成了flask.log日志文件。

2.3 输出到文件方式二

import logging
from flask import Flask, jsonify
from flask import current_app
from children import task
from flask.logging import default_handler
app = Flask(__name__)@app.route('/')
def default_route():"""Default route"""app.logger.debug('this is a DEBUG message')app.logger.info('this is an INFO message')app.logger.warning('this is a WARNING message')app.logger.error('this is an ERROR message')app.logger.critical('this is a CRITICAL message')task()return jsonify('hello world')@app.route('/current_app')
def default_route_current_app():current_app.logger.debug('this is a DEBUG message current app')task()return jsonify('hello world current app')if __name__ == '__main__':# 设置日志的记录等级logging.basicConfig(level=logging.DEBUG)# app.logger.removeHandler(default_handler)  # 是否移除默认配置# 创建日志记录器handler = logging.FileHandler('flask.log')# 定义handler的输出格式formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')handler.setFormatter(formatter)# 为全局的日志工具对象(flask app使用的)添加日志记录器logging.getLogger().addHandler(handler)# app.logger.addHandler(handler)app.run(host='0.0.0.0', port=8000)

有两种使用方式

import loggingfrom flask import current_app
def task():current_app.logger.info("I am children, current app")logging.info("I am children, logging")

在这里插入图片描述
在控制台输出时
若用current_app.logger,则标识main1(app的代码所在名称)
若用logging,则标识为root。

至此,Flask 的日志一切都运转良好。然后我们在生产服务器上部署的时候,现在常常会使用 Gunicorn 来运行,这时候的日志输出就有问题了,日志文件没有内容写入。

2.4 按天分割并调整格式

import logging
from flask import Flask, jsonify
from flask import current_app
from logging.handlers import TimedRotatingFileHandler
from children import task
app = Flask(__name__)@app.route('/')
def default_route():"""Default route"""app.logger.debug('this is a DEBUG message')app.logger.info('this is an INFO message')app.logger.warning('this is a WARNING message')app.logger.error('this is an ERROR message')app.logger.critical('this is a CRITICAL message')task()return jsonify('hello world')@app.route('/current_app')
def default_route_current_app():current_app.logger.debug('this is a DEBUG message current app')task()return jsonify('hello world current app')if __name__ == '__main__':print(app.debug)  # 默认为Falseapp.debug = Trueformatter = logging.Formatter("[%(asctime)s][%(filename)s:%(lineno)d][%(levelname)s][%(thread)d] - %(message)s")handler = TimedRotatingFileHandler("flask.log",when="D",interval=1,backupCount=30,encoding="UTF-8",delay=False,utc=False)handler.setFormatter(formatter)app.logger.addHandler(handler)app.run(host='0.0.0.0', port=8000)

3 使用gunicorn部署

Gunicorn有自己的日志记录器,它通过本身的机制控制日志级别。我们只能通过配置Gunicorn的日志设定,来实现我们的需求。同时,需要对上面例子应用的日志处理器设置进行调整。

3.1 方式一(gunicorn指定日志文件名)

import logging
from flask import Flask, jsonify
from flask import current_app
from logging.handlers import TimedRotatingFileHandler
from children import task
app = Flask(__name__)@app.route('/')
def default_route():"""Default route"""app.logger.debug('this is a DEBUG message')app.logger.info('this is an INFO message')app.logger.warning('this is a WARNING message')app.logger.error('this is an ERROR message')app.logger.critical('this is a CRITICAL message')task()return jsonify('hello world')@app.route('/current_app')
def default_route_current_app():current_app.logger.debug('this is a DEBUG message current app')task()return jsonify('hello world current app')# make app to use gunicorn logger handler
if __name__ != '__main__':gunicorn_logger = logging.getLogger('gunicorn.error')app.logger.handlers = gunicorn_logger.handlersapp.logger.setLevel(gunicorn_logger.level)if __name__ == '__main__':print(app.debug)  # 默认为Falseapp.debug = Trueformatter = logging.Formatter("[%(asctime)s][%(filename)s:%(lineno)d][%(levelname)s][%(thread)d] - %(message)s")handler = TimedRotatingFileHandler("flask.log",when="D",interval=1,backupCount=30,encoding="UTF-8",delay=False,utc=False)handler.setFormatter(formatter)app.logger.addHandler(handler)app.run(host='0.0.0.0', port=8000)

启动gunicorn

gunicorn -w 2 -b 0.0.0.0:5000 
--log-level debug 
--log-file /home/zb/mydir/gunicorn.log 
main:app

日志会写到文件gunicorn.log中。

3.2 方式二(自定义日志文件名)

nohup gunicorn -w 2 -b 127.0.0.1:8000 main1:app > /root/gunicorn.log 2>&1 &

为了使用自己设置的日志。
修改 app.py,注意我们添加的 if name != ‘main’ 这部分,就是在 Gunicorn 运行时,让Flask使用全局的日志处理器。

import logging
from flask import Flask, jsonify
from flask import current_app
from children import task
from flask.logging import default_handler
app = Flask(__name__)@app.route('/')
def default_route():"""Default route"""app.logger.debug('this is a DEBUG message')app.logger.info('this is an INFO message')app.logger.warning('this is a WARNING message')app.logger.error('this is an ERROR message')app.logger.critical('this is a CRITICAL message')task()return jsonify('hello world')@app.route('/current_app')
def default_route_current_app():current_app.logger.debug('this is a DEBUG message current app')task()return jsonify('hello world current app')if __name__ != "__main__":# 设置日志的记录等级logging.basicConfig(level=logging.DEBUG)# app.logger.removeHandler(default_handler)  # 是否移除默认配置# 创建日志记录器handler = logging.FileHandler('flask.log')# 定义handler的输出格式formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')handler.setFormatter(formatter)# 为全局的日志工具对象(flask app使用的)添加日志记录器logging.getLogger().addHandler(handler)if __name__ == '__main__':# 设置日志的记录等级logging.basicConfig(level=logging.DEBUG)# app.logger.removeHandler(default_handler)  # 是否移除默认配置# 创建日志记录器handler = logging.FileHandler('flask.log')# 定义handler的输出格式formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')handler.setFormatter(formatter)# 为全局的日志工具对象(flask app使用的)添加日志记录器logging.getLogger().addHandler(handler)# app.logger.addHandler(handler)app.run(host='0.0.0.0', port=8765)

4 执行flask后继续进行处理

可以解决这个报错的问题:python-“requests.exceptions.ConnectionError: (‘连接中止’, 远程断开连接(‘远程端关闭连接而没有响应’,))”。

需求:flask接口文件启动后,即时返回 ‘访问成功’,之后继续执行,文档中的功能函数。
方法:使用flask自带的一个函数即可解决。
flask_executor 模块。

from flask import Flask
from flask_executor import Executorimport time
app = Flask(__name__)
executor = Executor(app)@app.route('/fast', methods=["POST", "GET"])
def fast_response():def test_function():# 需要异步执行的代码time.sleep(10)print('test_functiony执行了')executor.submit(test_function)return '异步立即返回'@app.route('/slow', methods=["POST", "GET"])
def slow_response():def test_function():# 需要异步执行的代码time.sleep(10)print('test_functiony执行了')test_function()return '同步缓慢返回'if __name__=="__main__":app.run()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/226355.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java开发框架和中间件面试题(10)

目录 104.怎么保证缓存和数据库数据的一致性? 105.什么是缓存穿透,什么是缓存雪崩?怎么解决? 106.如何对数据库进行优化? 107.使用索引时有哪些原则? 108.存储过程如何进行优化? 109.说说…

听GPT 讲Rust源代码--src/tools(29)

File: rust/src/tools/clippy/clippy_lints/src/unused_peekable.rs 在Rust源代码中,rust/src/tools/clippy/clippy_lints/src/unused_peekable.rs这个文件是Clippy工具中一个特定的Lint规则的实现文件,用于检测未使用的Peekable迭代器。 Peekable迭代器…

[BUG] Hadoop-3.3.4集群yarn管理页面子队列不显示任务

1.问题描述 使用yarn调度任务时,在CapacityScheduler页面上单击叶队列(或子队列)时,不会显示应用程序任务信息,root队列可以显示任务。此外,FairScheduler页面是正常的。 No matching records found2.原…

Unreal Engine游戏引擎的优势

在现在这个繁荣的游戏开发行业中,选择合适的游戏引擎是非常重要的。其中,Unreal Engine作为一款功能强大的游戏引擎,在业界广受赞誉。那Unreal Engine游戏引擎究竟有哪些优势,带大家简单的了解一下。 图形渲染技术 Unreal Engin…

【计算机网络实验】educoder实验八 IPV6网络及其路由 头歌

第一关 IPV6网络基础 //千万不要破坏文档原有结构与内容!!! //以下均为判断题,F:表示错误,T:表示正确 //答案必须写在相应行末尾括号内,F与T二选一,大写 // 1、ipv6协议…

Flink1.17实战教程(第七篇:Flink SQL)

系列文章目录 Flink1.17实战教程(第一篇:概念、部署、架构) Flink1.17实战教程(第二篇:DataStream API) Flink1.17实战教程(第三篇:时间和窗口) Flink1.17实战教程&…

Azure 学习总结

文章目录 1. Azure Function1.1 Azure Function 概念1.2 Azure Function 实现原理1.3 Azure Function 本地调试1.4 Azure Function 云部署 2. Azure API Managment 概念 以及使用2.1 Azure API 概念2.2 Azure API 基本使用 3. Service Bus 应用场景及相关特性3.1 Service Bus 基…

django之drf框架(排序、过滤、分页、异常处理)

排序 排序的快速使用 1.必须是继承GenericAPIView及其子类才能是用排序 导入OrderingFilter类,from rest_framework.filters import OrderingFilter 2.在类中配置类属性 filter_backends[OrderingFilter] 3.类中写属性 ordering_fields [price,id] # 必须是表的…

【论文阅读】Realtime multi-person 2d pose estimation using part affinity fields

OpenPose:使用PAF的实时多人2D姿势估计。 code:GitHub - ZheC/Realtime_Multi-Person_Pose_Estimation: Code repo for realtime multi-person pose estimation in CVPR17 (Oral) paper:[1611.08050] Realtime Multi-Person 2D Pose Estima…

Docker安装Grafana

1. 介绍 Grafana 是一个开源的度量分析和可视化工具,可以通过将采集的数据分析、查询,然后进行可视化的展示,并能实现报警。参考官网地址:Run Grafana Docker image | Grafana documentation 2. 安装Grafana (1) . 下载 命令&…

中北大学 软件构造 U+及上课代码详解

作业1 1.数据类型可分为两类:(原子类型) 、结构类型。 2.(数据结构)是计算机存储、组织数据的方式,是指相互之间存在一种或多种特定关系的数据元素的集合 3.代码重构指的是改变程序的(结构)而不改变其行为,以便提高代码的可读性、易修改性等。 4.软件实…

HCIA-Datacom题库(自己整理分类的)——OSPF协议多选

ospf的hello报文功能是 邻居发现 同步路由器的LSDB 更新LSA信息 维持邻居关系 下列关于OSPF区域描述正确的是 在配置OSPF区域正确必须给路由器的loopback接配置IP地址 所有的网络都应在区域0中宣告 骨干区域的编号不能为2 区域的编号范围是从0.0.0.0到255.255.255.255…

Python基础语法总结

1.每条语句结束不需要分号(也可以加上), 直接换行, 注意: 如果两行代码写一行, 则必须加分号. 2.定义变量不需要指定类型(如果需要写类型, 需要在变量名后面加": 类型, 这个写法只是方便读代码). 3.变量名大小写敏感. 4.查看变量类型: type(变量名). 5.Python中的int表…

Grafana Loki 组件介绍

Loki 日志系统由以下3个部分组成: Loki是主服务器,负责存储日志和处理查询。Promtail是专为loki定制的代理,负责收集日志并将其发送给 loki 。Grafana用于 UI展示。 Distributor Distributor 是客户端连接的组件,用于收集日志…

目标检测-One Stage-YOLOv1

文章目录 前言一、YOLOv1的网络结构和流程二、YOLOv1的损失函数三、YOLOv1的创新点总结 前言 前文目标检测-Two Stage-Mask RCNN提到了Two Stage算法的局限性: 速度上并不能满足实时的要求 因此出现了新的One Stage算法簇,YOLOv1是目标检测中One Stag…

小梅哥Xilinx FPGA学习笔记18——专用时钟电路 PLL与时钟向导 IP

目录 一:IP核简介(具体可参考野火FPGA文档) 二: 章节导读 三:PLL电路原理 3.1 PLL基本实现框图 3.2 PLL倍频实现 3.3 PLL分频实现 四: 基于 PLL 的多时钟 LED 驱动设计 4.1 配置 Clocking Wizard 核 4.2 led …

腾讯云服务器和轻量服务器选哪个好(各自的优势区别)

腾讯云轻量服务器和云服务器CVM该怎么选?不差钱选云服务器CVM,追求性价比选择轻量应用服务器,轻量真优惠呀,活动 https://curl.qcloud.com/oRMoSucP 轻量应用服务器2核2G3M价格62元一年、2核2G4M价格118元一年,540元三…

Python入门-字符串Str

字符串 字符串 是Python中的 不可变 数据类型 1.字符串相关处理方法 大小写转换 # 大小写转换 s1HelloWorld new_s2s1.lower() print(s1,new_s2)new_s3s1.upper() print(new_s3)结果: D:\Python_Home\venv\Scripts\python.exe D:\Python_Home\chap6\示例6-1字符…

TICS Pro 配置时钟芯片

TICS Pro为TI公司提供的配置TI公司时钟芯片的软件,下载链接: TICS Pro. 软件使用 首先在设置选择找到需要配置的芯片,本文以LMX2571为例 红框中的前3行都可以设置芯片,第一个是选项卡设置,第二个是寄存器设置,第三个…

开箱即用的企业级数据和业务管理中后台前端框架Ant Design Pro 5的开箱使用和偏好配置

Ant Design Pro 介绍 Ant Design Pro 是一个开箱即用的企业级前端解决方案,基于 Ant Design 设计体系,提供了丰富的组件和功能,帮助开发者更快速地开发和部署企业级应用。 Ant Design Pro 使用 React、umi 和 dva 这三个主要的前端开发技术…