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://xiahunao.cn/news/2660680.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

什么是Wi-Fi Halow,它是基于什么标准,它的主要优势在哪

文章目录 1.1 背景1.2 技术前景2.1 Wi-Fi HaLow主要优势2.2 Wi-Fi HaLow技术特性2.3 具体技术特点2.4 支持频段介绍3.1 应用场景3.2 WiFi-HaLow芯片厂商3.3 基于WiFi-HaLow芯片网关与模组商1.1 背景 Wi-Fi HaLow是2021年11月Wi-Fi联盟发布的一项基于IEEE 802.11ah最新标准,专…

Spring Boot笔记1

1. SpringBoot简介 1.1. 原有Spring优缺点分析 1.1.1. Spring的优点分析 Spring是Java企业版(Java Enterprise Edition,javeEE)的轻量级代替品。无需开发重量级的Enterprise JavaBean(EJB),Spring为企业…

计算机网络:知识回顾

0 本节主要内容 问题描述 解决思路 1 问题描述 通过一个应用场景来回顾计算机网络涉及到的协议(所有层)。如下图所示场景: 学生Bob将笔记本电脑用一根以太网电缆连接到学校的以太网交换机;交换机又与学校的路由器相连&#xf…

“巴渝工匠杯”2022年重庆市职业院校技能大赛(高职组)云计算样题

“巴渝工匠杯”2022年重庆市职业院校技能大赛(高职组)云计算样题 需要软件包环境可私信博主 【赛程名称】云计算赛项第一场次-私有云 某企业拟使用OpenStack搭建一个企业云平台,以实现资源池化弹性管理、企业应用集中管理、统一安全认证和授…

OfficeWeb365 Indexs 任意文件读取漏洞复现

0x01 产品简介 OfficeWeb365 是专注于 Office 文档在线预览及PDF文档在线预览云服务,包括 Microsoft Word 文档在线预览、Excel 表格在线预览、Powerpoint 演示文档在线预览,WPS 文字处理、WPS 表格、WPS 演示及 Adobe PDF 文档在线预览。 0x02 漏洞概述 OfficeWeb365 /Pi…

《计算机网络管理》第五章 管简单网络管理协议思维导图

文章目录 说明概述。1 SNMP演变2 SNMPv12.1 简介2.2 SNMPv1协议数据单元2.3 报文发送与接收(了解)2.4 SNMPv1操作2.4.1 检索简单对象2.4.1.1 举例 2.4.2 表的更新和删除 2.5 SNMPv1的局限性(了解) 3 SNMPv23.1 SNMPv2管理信息结构…

聚焦亚马逊云科技 re:Invent re:Cap专场,重构生成式AI的无限可能!

摘要:12月14日至17日,第十二届全球软件案例研究峰会(简称TOP100summit)在北京国际会议中心成功举办,亚马逊云科技资深开发者布道师郑予彬、亚马逊云科技解决方案研发中心应用科学家肖宇、可以科技产品负责人曹临杰、亚马逊云科技解决方案架构…

架构设计系列 5:常见架构介绍

前面讲了架构是什么,架构的发展史,架构设计的基础理论,这次针对常见架构设计风格进行介绍和分析。 一、MVC:三层架构经典 经典的 MVC 架构(Model-View-Controller)架构是软件系统架构设计中的经典&#xf…

提升设计效率:全面了解如何使用Figma插件

Figma组件库包括颜色、字体、图标、按钮、阴影、圆角、间距等。当Figma组件库的样式和Figma组件达到一定数量时,将难以维护,设计和开发的对接成本将大大提高。Figma可以在同一母版下单独设置样式,而不影响与母版之前的关系,这是Sk…

前端基础:Vue搞笑白话文(工作之余瞎写)

1、data:{}与data(){return{}}这两个是个什么鬼? vue实例 new Vue({el:#app,data:{name:李四}}) 组件实例 const aaa Vue.extent({data(){return {name:}} }) 为什么Vue实例可以那么写而组件实例就不行了?原因就是因为在底层原理上,组件…

学习使用wps将ppt的页面保存为图片的方法

学习使用wps将ppt的页面保存为图片的方法 方案 方案 1、打开ppt,点击文件,另存为,选择文件类型为图片格式,jpg或者png,如下图: 2、点击每张幻灯片

springcloud中使用openfeign来优化接口调用

简单介绍在springcloud中使用openfeign来优化接口调用 目录 一、引入依赖二、为服务提供者编写openfeign接口三、服务消费者调用定义的openfeign接口四、项目结构五、日志级别配置1、通过配置类进行全局配置2、通过配置类进行局部配置3、通过配置文件配置 一、引入依赖 <!-…

Hive中支持毫秒级别的时间精度

实际上&#xff0c;Hive 在较新的版本中已经支持毫秒级别的时间精度。你可以通过设置 hive.exec.default.serialization.format 和 mapred.output.value.format 属性为 1&#xff0c;启用 Hive 的时间精度为毫秒级。可以使用以下命令进行设置&#xff1a; set hive.exec.defau…

音频修复和增强软件:iZotope RX 10 (Win/Mac)中文汉化版

iZotope RX 是一款专业的音频修复和增强软件&#xff0c;一直是电影和电视节目中使用的行业标准音频修复工具&#xff0c;iZotope能够帮助用户对音频进行制作、后期合成处理、混音以及对损坏的音频进行修复&#xff0c;再解锁更多功能之后还能够对电影、游戏、电视之中的音频进…

OSPF被动接口配置-新版(14)

目录 整体拓扑 操作步骤 1.基本配置 1.1 配置R1的IP 1.2 配置R2的IP 1.4 配置R4的IP 1.5 配置R5的IP 1.6 配置PC-1的IP地址 1.7 配置PC-2的IP地址 1.8 配置PC-3的IP地址 1.9 配置PC-4的IP地址 1.10 检测R1与PC3连通性 1.11 检测R2与PC4连通性 1.12 检测R4与PC1连…

unity学习笔记----游戏练习02

一、阳光值的展示和消耗 1.创建一个文本组件用于显示阳光的数值&#xff0c;然后在脚本中得到这个UI。 在SunManger中得到这个组件的引用 public TextMeshProUGUI sunPointText; 写一个用于更新显示的方法 public void UpdataSunPointText() { sunPointText.tex…

计算机网络(6):应用层

每个应用层协议都是为了解决某一类应用问题&#xff0c;而问题的解决又往往是通过位于不同主机中的多个应用进程之间的通信和协同工作来完成的。 应用层的具体内容就是规定应用进程在通信时所遵循的协议。 应用层的许多协议都是基于客户服务器方式。即使是对等通信方式&#x…

Grafana Loki 组件介绍

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

uniapp:实现手机端APP登录强制更新,从本地服务器下载新的apk更新,并使用WebSocket,实时强制在线用户更新

实现登录即更新&#xff0c;或实时监听更新 本文介绍的是在App打开启动的时候调用更新&#xff0c;点击下方链接&#xff0c;查看使用WebSocket实现实时通知在线用户更新。 uniapp&#xff1a;全局消息是推送&#xff0c;实现app在线更新&#xff0c;WebSocket&#xff0c;ap…

《MySQL系列-InnoDB引擎01》MySQL体系结构和存储引擎

文章目录 第一章 MySQL体系结构和存储引擎1 数据库和实例2 MySQL配置文件3 MySQL数据库路径4 MySQL体系结构5 MySQL存储引擎5.1 InnoDB存储引擎5.2 MyISAM存储引擎5.3 NDB存储引擎5.4 Memory存储引擎5.5 Archive存储引擎5.6 Federated存储引擎 6 连接MySQL6.1 TCP/IP6.2 命名管…