Python系列:将Flask 日志整合到Gunicorn日志并输出、Flask结合gunicorn和nginx反向代理的生产环境部署及踩坑记录




一. 将Flask 日志整合到Gunicorn日志并输出

Example Code

# coding: utf-8

import logging

from flask import Flask, jsonify


app = Flask(__name__)


@app.route('/')
def index():
    app.logger.debug('this is debug message')
    app.logger.error('this is error message')
    app.logger.critical('this is critical message')
    return 'ok'


if __name__ != '__main__':
    # 如果不是直接运行,则将日志输出到 gunicorn 中
    gunicorn_logger = logging.getLogger('gunicorn.error')
    app.logger.handlers = gunicorn_logger.handlers
    app.logger.setLevel(gunicorn_logger.level)


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8000, debug=True)

Run:

gunicorn --workers=2 --bind=0.0.0.0:8000 --log-level=debug gunicorn_log:app

在这里插入图片描述




二. Flask结合gunicorn和nginx反向代理的生产环境部署及踩坑记录

之前自己写的flask使用gunicorn上线生产环境没有什么问题,但是最近搭建了一个现成的flask项目,当使用python直接运行时不会有问题,而使用gunicorn时则会出现一些问题。

2|0部署过程

2|1运行测试

这里使用pyenv创建了一个虚拟环境,并安装好依赖

pyenv virtualenv 3.9.6 freegpt pyenv activate freegpt pip install -r requirements.txt

下面是入口函数run.py:

from server.app import app 
from server.website import Website 
from server.backend import Backend_Api 
from json import load 

if __name__ == '__main__': 

# Load configuration from config.json config = load(open('config.json', 'r')) site_config = config['site_config'] 

# Set up the website routes site = Website(app) for route in site.routes: app.add_url_rule( route, view_func=site.routes[route]['function'], methods=site.routes[route]['methods'], ) 

# Set up the backend API routes backend_api = Backend_Api(app, config) for route in backend_api.routes: app.add_url_rule( route, view_func=backend_api.routes[route]['function'], methods=backend_api.routes[route]['methods'], ) 

# Run the Flask server print(f"Running on port {site_config['port']}") app.run(**site_config) print(f"Closing port {site_config['port']}")

其中site_config.json文件如下:

{ "site_config": { "host": "127.0.0.1", "port": 1234, "debug": false }, "use_auto_proxy": false }

意思是,运行flask服务于127.0.0.1:1234,只运行本地访问,后期我们需要搭建Nginx进行反向代理。

我们先使用python直接运行测试一下看能否跑起来以及能否正常访问。

python run.py

在这里插入图片描述

我们在服务器使用curl进行请求

curl 127.0.0.1:1234

在这里插入图片描述

数据返回正常,说明可以正常访问。

2|2gunicorn搭建

Gunicorn是一个WSGI HTTP Server,是针对Python的、在Unix系统上运行的、用来解析HTTP请求的网关服务。

它的特点是:能和大多数的Python web框架兼容;使用简单;轻量级的资源消耗;高性能。

首先在当前虚拟环境下安装gunicorn

pip install gunicorn

然后我们使用gunicorn将flask项目跑起来,并且仅对本机开放,端口4444

gunicorn run:app -b 127.0.0.1:4444 --access-logfile access.log --error-logfile error.log &

使用ps命令可以看到当前已经成功在后台运行起来了

ps aux | grep gunicorn

在这里插入图片描述

踩坑

但是此时当我们再次使用curl访问127.0.0.1:4444时:
在这里插入图片描述

出现了404的错误。

我们查看gunicorn生成的日志文件:

# access.log 127.0.0.1 - - [13/Jul/2023:12:51:11 -0400] "GET / HTTP/1.1" 404 207 "-" "curl/7.76.1"

可以看到成功的请求到了我们的wsgi server,但是返回了404。在外网论坛上摸索了一番,问题出在了run.py上。

run.py文件中的所有代码都是写在if __name__ == "__main__":之下的,这在python语法中代表着主函数入口。

  • 当使用Python直接运行脚本时(例如:python run.py),if __name__ == '__main__'条件下的代码块会被执行,包括app.run()。这将启动Flask服务器,并让应用程序开始监听指定的主机和端口。

  • 当使用Gunicorn运行应用程序时(例如:gunicorn --bind 127.0.0.1:4444 run:app),if __name__ == '__main__'条件下的代码块不会被执行。因为Gunicorn实际上是将你的代码作为一个模块导入,而不是直接运行该代码。在这种情况下,Gunicorn会在内部处理Flask服务器的启动逻辑,并监听指定的主机和端口。也就因此自己在app.run(**kwargs)中设定的host、port、debug等参数也就失效了。

因此,无论是使用Python直接运行还是使用Gunicorn运行应用程序,app.run()只会在Python直接运行脚本时执行。而在使用Gunicorn运行时,if __name__ == '__main__'条件下的代码块将被跳过,包括app.run()。这是因为Gunicorn已经处理了服务器的启动逻辑。

因此,if __name__ == '__main__'条件的目的是为了确保在直接运行脚本时才执行特定的代码块,而在被导入为模块时跳过这些代码块。这样可以确保在使用Gunicorn启动应用程序时不会重复启动Flask服务器,并避免出现意外行为。

解决方案

既然已经知道了错误的逻辑,那么解决方法就很简单了,只要把除了app.run()的其他代码全部移出if __name__ == "__main__"即可。修改后的run.py如下:

from server.app import app 

from server.website import Website 

from server.backend import Backend_Api 

from json import load 

# Load configuration from config.json 
config = load(open('config.json', 'r')) 
site_config = config['site_config'] 

# Set up the website routes site = Website(app) for route in site.routes: app.add_url_rule( route, view_func=site.routes[route]['function'], methods=site.routes[route]['methods'], ) 

# Set up the backend API routes backend_api = Backend_Api(app, config) for route in backend_api.routes: app.add_url_rule( route, view_func=backend_api.routes[route]['function'], methods=backend_api.routes[route]['methods'], ) 
if __name__ == '__main__': 

# Run the Flask server 

print(f"Running on port {site_config['port']}") 

app.run(**site_config) 

print(f"Closing port {site_config['port']}")

这样就可以保证python和gunicorn方式均可正常运行。

先kill掉之前正在运行的gunicorn,并重新启动

kill -9 1275864 1275865 gunicorn run:app -b 127.0.0.1:4444 --access-logfile access.log --error-logfile error.log &

可以看到现在请求127.0.0.1:4444已经正确响应了

在这里插入图片描述

2|3Nginx反向代理

目前搭建的服务只能服务器自己访问到,下面我们通过nginx反向代理将其映射到对外的80端口

安装配置nginx就不多说了,下面讲讲配置文件的写法。其实很简单

vim /etc/nginx/nginx.conf
# nginx.conf ... server { listen 80; server_name xxxxxxxx; # 此处填绑定的域名 location / { proxy_pass http://localhost:4444; proxy_set_header Host $host:$server_port; proxy_set_header X-Real-IP $remote_addr; } } ...

然后运行nginx即可

nginx -t nginx

此时使用本机访问域名的80端口已可以正常访问了。










慕斯炖蘑菇

将Flask 日志整合到Gunicorn日志并输出

野生的狒狒

Flask结合gunicorn和nginx反向代理的生产环境部署及踩坑记录

  • 22
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
nginx是一个高性能的HTTP和反向代理服务器,可以用来处理静态文件和动态请求。gunicorn是一个Python WSGI HTTP服务器,可以将Flask应用程序部署生产环境中。supervisor是一个进程控制系统,可以用来管理和监控进程。这三个工具可以一起使用来部署Flask应用程序。 以下是使用nginxgunicorn和supervisor部署Flask应用程序的步骤: 1. 安装nginxgunicorn和supervisor。 2. 编写Flask应用程序,并使用工厂函数构建应用程序对象。 3. 创建一个gunicorn配置文件,例如gunicorn.conf.py,指定工作进程数和线程数。 4. 使用gunicorn启动Flask应用程序,例如: ```shell gunicorn -c gunicorn.conf.py "my_project:create_app()" ``` 这将启动一个gunicorn进程,监听8000端口,并将请求转发到Flask应用程序。 5. 配置nginx,将请求转发到gunicorn进程。例如,在nginx.conf文件中添加以下内容: ```nginx server { listen 80; server_name example.com; location / { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } ``` 这将将所有请求转发到gunicorn进程,并将请求头中的一些信息传递给Flask应用程序。 6. 使用supervisor管理gunicorn进程。例如,在supervisor.conf文件中添加以下内容: ```ini [program:gunicorn] command=/path/to/gunicorn -c /path/to/gunicorn.conf.py "my_project:create_app()" directory=/path/to/project user=user autostart=true autorestart=true stopasgroup=true killasgroup=true ``` 这将启动一个名为gunicorn的进程,并在系统启动时自动启动该进程。如果该进程崩溃或被杀死,supervisor将自动重新启动该进程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

坦笑&&life

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值