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()
相关文章:

python-39-flask+nginx+Gunicorn的组合应用
flask nginx Gunicorn 王炸 1 flasknginxgunicornsupervisor 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端口…...

C#-CSC编译环境搭建
一.Microsoft .NET Framework 确保系统中安装Microsoft .NET Framework相关版本下载 .NET Framework 4.7 | 免费官方下载 (microsoft.com)https://dotnet.microsoft.com/zh-cn/download/dotnet-framework/net47 二.编译环境搭建 已经集成编译工具csc.exe,归档至gitcode,实现us…...

【JVM】一文掌握JVM垃圾回收机制
作为Java程序员,除了业务逻辑以外,随着更深入的了解,都无法避免的会接触到JVM以及垃圾回收相关知识。JVM调优是一个听起来很可怕,实际上很简单的事。 感到可怕,是因为垃圾回收相关机制都在JVM的C++层实现,我们在Java开发中看不见摸不着;而实际很简单,是因为它说到底,也…...

【AIGC风格prompt】风格类绘画风格的提示词技巧
风格类绘画风格的提示词展示 主题:首先需要确定绘画的主题,例如动物、自然景观、人物等。 描述:根据主题提供详细的描述,包括颜色、情感、场景等。 绘画细节:描述绘画中的细节,例如表情、纹理、光影等。 场…...
vue exceljs json数据转excel
json数据转excel 有时候我们会遇到这样一个需求,就是将数据转成excel下载,这一般都是由后端来处理,使用插件poi轻松搞定。如果只有少量数据,那么能不能避免调用后端接口,前端直接处理呢? 答案是ÿ…...

Navicat for MySQL 创建函数——报错1418
解决方法 1查看是否开启了创建函数的功能 输入下面语句查看是否开启了创建函数的功能 show variables like %func%; 下面为创建函数功能为开启的查询结果 如果不是上面的结果可以用下面的语句修改为开启 set GLOBAL log_bin_trust_function_creatorstrue; //或 set GLOBAL …...

java球队信息管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目
一、源码特点 java Web球队信息管理系统是一套完善的java web信息管理系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发,数据库为Mysql5…...

设计模式(4)--对象行为(7)--观察者
1. 意图 定义对象间的一种一对多的依赖关系, 当一个对象的状态改变时,所有依赖于它的对象都得到通知并被自动更新。 2. 四种角色 抽象目标(Subject)、具体目标(Concrete Subject)、抽象观察者(Observer)、 具体观察者(Concrete Observer) 3. 优点 3.1 …...

MySQL所有常见问题
一、事务 定义:一组操作要么全部成功,要么全部失败,目的是为了保证数据最终的一致性 在MySQL中,提供了一系列事务相关的命令: start transaction | begin | begin work:开启一个事务commit:提交一个事务rollback:回滚一个事务事务的ACID 原子性(Atomicity):当前事…...
锐捷交换机配置 SNMP
配置步骤 ( SNMP v2 ) 步骤一 -- 创建共同体(Community) ruijie(config)#snmp-server community test rw # rw 为读和写口令ruijie(config)#snmp-server community public ro # ro 为只读和写口令这里的共同体为“test”,通常只读口令和读写口令单独配置,提升安…...

Windows 10 安装和开启VNCServer 服务
Windows 10 安装和开启VNCServer 服务 登录云服务器 使用本地RDP登录到配置VNCServer服务的Windows10系统的云服务器。 下载VNC Server安装包 打开官网下载VNCServer安装包 URL:https://www.realvnc.com/en/connect/download/vnc/windows/ 安装VNC Server 双击…...

js遍历后端返回的集合将条件相同的放入同一个数组内
项目场景: echarts折线图需要根据条件动态展示多条不同曲线 解决方案: 后端直接将使用sql将数据查询出来返回即可,因为我这里不是Java使用的C#不是很熟练后台不好写逻辑,所以在前端js完成的 代码如下: function createline(villagename, buildingname…...

GcExcel:DsExcel 7.0 for Java Crack
GcExcel:DsExcel 7.0-高速 Java Excel 电子表格 API 库 Document Solutions for Excel(DsExcel,以前称为 GcExcel)Java 版允许您在 Java 应用程序中以编程方式创建、编辑、导入和导出 Excel 电子表格。几乎可以部署在任何地方。 创建、加载、…...
基于SpringBoot的职业生涯规划系统
文章目录 项目介绍主要功能截图:部分代码展示设计总结项目获取方式🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 项目介绍 基于SpringBoot的职业生涯规划系统,java…...

基于Java+SpringBoot+vue+elementui的校园文具商城系统详细设计和实现
基于JavaSpringBootvueelementui的校园文具商城系统详细设计和实现 欢迎点赞 收藏 ⭐留言 文末获取源码联系方式 文章目录 基于JavaSpringBootvueelementui的校园文具商城系统详细设计和实现前言介绍:系统设计:系统开发流程用户登录流程系统操作流程 功能…...
PyTorch中常用的工具(5)使用GPU加速:CUDA
文章目录 前言4 使用GPU加速:CUDA5 小结 前言 在训练神经网络的过程中需要用到很多的工具,最重要的是数据处理、可视化和GPU加速。本章主要介绍PyTorch在这些方面常用的工具模块,合理使用这些工具可以极大地提高编程效率。 由于内容较多&am…...
Qt+opencv 视频分解为图片
最近遇到一些售前提供的BUG,但是他们提供的是录像视频,因为处理显示速度比较快,因此很难找到出现问题的位置。需要反复播放,自己编写了一个视频分解成图片这样就可以一张图一张图的对比,方便查看。 开发环境 qtopenv…...
一篇文章认识微服务的优缺点和微服务技术栈
目录 1、微服务 2、微服务架构 3、微服务优缺点 3.1 优点 3.2 缺点 4、微服务技术栈 1、微服务 微服务化的核心就是将传统的一站式应用,根据业务拆分成一个一个的服务,彻底地去耦合,每一个微服务提供单个业务功能的服务,一…...
[spark] dataframe的数据导入Mysql5.6
在 Spark 项目中使用 Scala 连接 MySQL 5.6 并将 DataFrame 中的数据保存到 MySQL 中的步骤如下: 添加 MySQL 连接驱动依赖: 在 Spark 项目中,你需要在项目的构建工具中添加 MySQL 连接驱动的依赖。 如果使用 Maven,可以在 pom.xm…...

2023年度业务风险报告:四个新风险趋势
目录 倒票的黄牛愈加疯狂 暴增的恶意网络爬虫 愈加猖獗的羊毛党 层出不穷的新风险 业务风险呈现四个趋势 防御云业务安全情报中心“2023年业务风险数据”统计显示,恶意爬虫风险最多,占总数的37.8%;其次是虚假账号注册,占18.79%&am…...

XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...

K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...

nnUNet V2修改网络——暴力替换网络为UNet++
更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...
Python 高效图像帧提取与视频编码:实战指南
Python 高效图像帧提取与视频编码:实战指南 在音视频处理领域,图像帧提取与视频编码是基础但极具挑战性的任务。Python 结合强大的第三方库(如 OpenCV、FFmpeg、PyAV),可以高效处理视频流,实现快速帧提取、压缩编码等关键功能。本文将深入介绍如何优化这些流程,提高处理…...
华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)
题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...
命令行关闭Windows防火墙
命令行关闭Windows防火墙 引言一、防火墙:被低估的"智能安检员"二、优先尝试!90%问题无需关闭防火墙方案1:程序白名单(解决软件误拦截)方案2:开放特定端口(解决网游/开发端口不通)三、命令行极速关闭方案方法一:PowerShell(推荐Win10/11)方法二:CMD命令…...
零基础在实践中学习网络安全-皮卡丘靶场(第十一期-目录遍历模块)
经过前面几期的内容我们学习了很多网络安全的知识,而这期内容就涉及到了前面的第六期-RCE模块,第七期-File inclusion模块,第八期-Unsafe Filedownload模块。 什么是"遍历"呢:对学过一些开发语言的朋友来说应该知道&…...