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.mzph.cn/news/589716.shtml

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

相关文章

CSS去掉按钮阴影 | css去掉按钮边框 | 注意改变搜索的关键词、搜索方式

上图是在谷歌浏览器中运行的结果 button {box-shadow: none;height: 50px;width: 100px;background-color: white;border-color: white; }写了以上的css,发现按钮还是有阴影一样的东西,查阅网络资料的时候也一直在搜索“如何去掉按钮阴影”,…

Linux调试工具—gdb

🎬慕斯主页:修仙—别有洞天 ♈️今日夜电波:HEART BEAT—YOASOBI 2:20━━━━━━️💟──────── 5:35 🔄 ◀️ ⏸ ▶️ ☰ …

【Delphi】IOS上架踩坑记 - 2024年第一天

目录 一、前言: 二、IOS程序上架网址 三、踩坑记 1. 关于版本中的 CFBundleIdentifier 参数(Transporter 提示) 2. IOS APP 程序图标要求(Transporter 提示) 3. 关于版本中的 CFBundleShortVersionString 参数&a…

收入支出记录,对需要的账目明细进行颜色标记

面对繁杂的账单和财务数据,你是否曾为记账而感到苦恼?别担心,我们为你带来了一款全新的记账软件——晨曦记账本,这不仅仅是一个简单的记账工具,更是你财务管理的得力助手。 所需工具: 一个【晨曦记账本】…

【C++】Windows编译FileZilla Client

按照Compiling FileZilla 3 under Windows - FileZilla Wiki (filezilla-project.org)操作即可。 1.下载安装MSYS2 msys2-x86_64-20220118.exe 2.更新MSYS2 进入MSYS2 MinGW 64-bit shell,运行 pacman -Syu重复退出shell,更新MSYS2。直到没有可更新…

java servlet软件缺陷库管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java servlet软件缺陷库管理系统是一套完善的java web信息管理系统 系统采用serlvetdaobean(mvc模式),对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为TOM…

docker小白第十天

redis集群主从容错切换案例 3主3从的redis集群,某个主机宕机了,需要对应的从机补位。 docker exec -it redis-node-1 /bin/bash # 进入容器1的命令行 redis-cli -p 6381 # 进入节点1的命令行 cluster nodes # 查看集群信息可以看到1号和6号对应是主从关…

基于Java SSM框架实现房屋租赁合同系统项目【项目源码+论文说明】计算机毕业设计

基于java的SSM框架实现房屋租赁合同系统演示 摘要 在网络高速发展的时代,众多的软件被开发出来,给用户带来了很大的选择余地,而且人们越来越追求更个性的需求。在这种时代背景下,人们对房屋租赁系统越来越重视,更好的…

C++/CLI——2类和对象生存期

C/CLI——2函数与类的使用方法 函数使用 定义函数和使用函数基本与C#相同,只不过C/CLI可以像标准C一样,可以先声明函数原型,再定义函数主体。值得注意的是,如果有默认参数,只能在函数原型中定义,不能在函…

桉木芯建筑模板与其他材质比较有何不同?

在建筑行业中,模板的选择对于确保工程质量和效率至关重要。桉木芯建筑模板作为市场上的一种选择,与其他材质的模板相比,具有独特的优势。能强优品木业作为专业的桉木芯建筑模板生产厂家,其产品充分展示了这一材质的优越性能。 材质…

计算机组成原理复习5

总线结构与控制 文章目录 总线结构与控制总线结构单总线结构双总线结构三总线结构四总线结构 总线控制判优控制(仲裁逻辑)链式查询方式计数器定时查询独立请求方式 通信控制同步通信异步通信两种传输率的异步串行传送字符格式 总线结构 单总线结构 单总…

亿级流量场景下如何优化混合回收

大白话: 我们完全可以通过最大停顿时间的调整,来控制每次垃圾回收的region数量以及回收垃圾大小。 大白话: 1.是已分配内存占总内存的超过45%阈值; 2.优化G1垃圾回收关键的一点,设置合理的最大停顿时间。 大白话&#…

打破数据孤岛:ChatGPT如何打通金融大数据的任督二脉?

文章目录 一、引言二、ChatGPT与金融大数据分析的融合三、实践应用:ChatGPT在金融大数据分析中的优势与挑战四、案例分析:ChatGPT在金融大数据分析中的应用案例五、前景展望:ChatGPT在金融大数据分析领域的未来发展《AI时代Python金融大数据分…

数据仓库-数仓优化小厂实践

一、背景 由于公司规模较小,大数据相关没有实现平台化,相关的架构都是原生的Apache组件,所以集群的维护和优化都需要人工的参与。根据自己的实践整理一些数仓相关的优化。 二、优化 1、简易架构图 2、ODS层优化 2.1 分段式解析 随着业务增长…

多边形的填充算法的分析

多边形的填充 分析 思路一 我们之前已经实现了对直线的扫描转换,但是现在我们遇到了新的问题那就是如何对多边形进行填充,如图所示,如何对图示的多边形进行填充呢? 我所想到的第一个办法是这样的,那就是假设上顶点…

webRTC实时通信demo

参考文档: https://www.jianshu.com/p/f439ce5cc0be https://www.w3cschool.cn/socket demo流程示意图(用户A向用户B推送视频): #mermaid-svg-0KZaDQ5DBl28zjmZ {font-family:"trebuchet ms",verdana,arial,sans-seri…

总结—elasticsearch启动失败的几种情况及解决

转载说明:如果您喜欢这篇文章并打算转载它,请私信作者取得授权。感谢您喜爱本文,请文明转载,谢谢。 摘要 本文主要梳理从ES初学以来所遇到的启动失败的几种情况。 1、使用root用户启动失败 在有一次搭建elasticsearch的时候&am…

【Linux】—— 匿名管道

前言: 接下来我将带大家探索 进程间通信 的方式。本期,要讲的就是管道其中之一“匿名管道”!! 目录 (一)进程间通信介绍 1、进程间通信目的 2、进程间通信发展 3、进程间通信分类 (二&…

文件分片上传(模拟网盘效果)

文件分片上传(模拟网盘效果) 文章说明简单模拟拖拽文件夹和选择文件的进度条效果效果展示结合后端实现文件上传效果展示加上分片的效果效果展示加上MD5的校验,实现秒传和分片的效果后续开发说明源码下载 文章说明 文章主要为了学习文件上传&a…

2024年【黑龙江省安全员C证】考试及黑龙江省安全员C证找解析

题库来源:安全生产模拟考试一点通公众号小程序 2024年黑龙江省安全员C证考试为正在备考黑龙江省安全员C证操作证的学员准备的理论考试专题,每个月更新的黑龙江省安全员C证找解析祝您顺利通过黑龙江省安全员C证考试。 1、【多选题】下列属于编制安全检查…