gpt4 book ai didi

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

转载 作者:我是一只小鸟 更新时间:2023-07-14 06:31:06 30 4
gpt4 key购买 nike

前言

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


部署过程

运行测试

这里使用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

                        
                      

image-20230714004534660

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

                        
                          curl 127.0.0.1:1234

                        
                      

image-20230714004621346

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


gunicorn搭建

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

                        
                      

image-20230714005029807

踩坑

但是此时当我们再次使用curl访问127.0.0.1:4444时:

image-20230714005121785

出现了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 已经正确响应了 。

image-20230714010629837


Nginx反向代理

目前搭建的服务只能服务器自己访问到,下面我们通过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端口已可以正常访问了.

image-20230714011222108

最后此篇关于Flask结合gunicorn和nginx反向代理的生产环境部署及踩坑记录的文章就讲到这里了,如果你想了解更多关于Flask结合gunicorn和nginx反向代理的生产环境部署及踩坑记录的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com