生产服务器 Flask 多并发支持,基于 Gunicorn

文章目录

    自从用了 Golang 开发服务端之后,好多年没有经历部署 Python 服务的苦恼。
    但是由于要开发 Rasa 相关的服务,为了统一语言,还是继续使用了 Python Flask 框架。
    又一次体验部署 Python 生产环境的艰辛。

    需求

    需要将 Python Flask 写的一个接口服务部署到生产服务器。

    目前 Flask 部署在 docker 中,依然是以 debug 模式运行,无法同时响应多个请求。

    所以需求是:

    1. 找到 Flask 生产环境部署方式
    2. 适合 docker 部署

    gunicorn 支持并发的原理

    我看大部分推荐的部署方式是 gunicorn, 对于 Flask / Django 均适用。

    Gunicorn ‘Green Unicorn’ is a Python WSGI HTTP Server for UNIX.

    Gunicorn(Green Unicorn)是一个基于 Python 的 Web Server,它所在的位置通常是在反向代理(Nginx)和一个 python web 应用之间。Gunicorn 的并发原理:

    1. 多进程模型:Gunicorn 使用多进程模型来实现并发处理。它通过创建多个子进程来处理传入的请求。每个子进程都是一个独立的工作进程,可以同时处理一个或多个请求。
    2. 主进程和工作进程:Gunicorn启动时会创建一个主进程和多个工作进程。主进程负责监听网络请求并将其分发给工作进程。工作进程是实际处理请求的进程。
    3. 监听端口和负载均衡:主进程在一个或多个网络接口上监听来自客户端的请求。当请求到达时,主进程使用负载均衡算法(如轮询或并发连接数)将请求分发给可用的工作进程。这样可以实现请求的平衡分配和并发处理。
    4. 独立的工作进程:每个工作进程都是独立的,它们在自己的进程空间中执行,并处理分配给它们的请求。由于每个工作进程都是独立的,它们之间不会共享内存,从而确保了请求处理的隔离性和安全性。
    5. 非阻塞I/O:Gunicorn使用非阻塞I/O(Non-blocking I/O)来提高并发性能。工作进程使用非阻塞方式处理请求和响应,可以在等待I/O操作(如读写文件、网络通信)时同时处理其他请求,提高了系统的吞吐量和响应速度。

    如何确定需要几个工作进程

    Gunicorn relies on the operating system to provide all of the load balancing when handling requests. Generally we recommend (2 x $num_cores) + 1 as the number of workers to start off with.

    即如果是双核,则需要 2x2+1 = 5 个 worker 进程。

    参考:

    https://docs.gunicorn.org/en/stable/design.html

    安装 gunicorn

    pip install gunicorn
    

    加入到 requirements.txt 是好习惯,也方便 docker 中使用。

    启动 gunicorn

    如果在 docker 中使用,可以创建一个 gunicorn.sh shell 脚本:

    #!/bin/bash
    
    gunicorn main:app -w 3 -b 0.0.0.0:8003
    

    即便不使用 docker,保留运行命令的脚本也是必要的,避免忘记。

    修改 dockerfile

    将 ENTRYPOINT 由 python 直接执行 flask 代码改成 gunicorn.sh

    FROM python:3
    
    #RUN apt−get −y update
    #RUN apt−get install −y pip3 build−essential
    
    COPY . .
    RUN pip install -r requirements.txt
    
    #ENTRYPOINT ["python"]
    #CMD ["main.py"]
    
    ENTRYPOINT ["./gunicorn.sh"]
    

    docker compose 端口映射

    ports:
      - 8003:8003
    

    Nginx 配置

    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    
    proxy_pass http://127.0.0.1:8003;
    

    跟之前 Gunicorn 部署 Django 项目的配置 是一样的。

    参考

    • https://betterprogramming.pub/create-a-running-docker-container-with-gunicorn-and-flask-dcd98fddb8e0
    • https://zhuanlan.zhihu.com/p/618533248

    关于作者 🌱

    我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊,或者关注我的个人公众号“大象工具”, 查看更多联系方式