Logo

Flask – 常见应用部署方案

photo

2026年02月14日

前言

在开发 Flask 应用时,通常会直接使用内置的 WSGI Server 来运行项目。这种方式简单易用,非常适合开发和调试阶段。然而,Flask 的内置 WSGI Server 性能较弱,无法满足生产环境的高并发和性能要求。因此,在实际生产中,更推荐使用专门的 WSGI 服务工具,如 gunicorn,来替代内置的服务器。

Flask部署方案概览

对于老项目来说,如果代码中大量使用单进程内的内存级共享变量,直接切换到高性能的多进程模式(如使用 gunicorn 的多 worker 模式)可能会导致数据访问不一致的问题。此时,可以选择使用 gevent,一种基于协程的运行模式,能很好地支持单进程共享变量的场景,同时提升效率。

在容器技术尚未流行的时期,生产环境中部署 Flask 项目通常采用虚拟环境(virtualenv)来隔离依赖,并结合 gunicorn 作为 WSGI 服务管理工具,再通过 supervisor 或其他进程守护工具实现自动启动和故障恢复。这种方式在传统服务器环境中较为常见,但随着 Docker 的兴起,这种方法逐渐被替代。

现在,随着容器编排工具的普及,生产环境部署 Flask 项目更多地采用 Kubernetes 等现代化的方式。通过 Kubernetes 的 serviceingress(或使用高级工具如 istio)可以轻松实现流量管理、负载均衡和服务发现。这种方式不仅提升了部署效率,还增强了系统的可扩展性和容错能力。

  • 开发阶段:使用 Flask 的内置 WSGI Server 运行应用。
  • 需要单进程共享变量:选择 gevent 模式。
  • 传统部署方式:虚拟环境 + gunicorn + supervisor。
  • 现代部署方式:使用 Kubernetes 的服务编排和流量管理。

运行方式

在开发 Flask 应用时,运行方式的选择通常取决于场景需求和环境特性。以下是几种常见的运行方式及其适用场景。

1. 开发阶段:使用 Flask 内置 WSGI Server

Flask 自带一个简单的 WSGI Server,通过调用 app.run() 即可启动。这种方式非常适合开发阶段的快速调试,因为它操作简单且无需额外安装组件。例如:

from flask import Flask

app = Flask(__name__)

@app.route("/test")
def test():
    return "Hello, Flask!"

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)

但需要注意,这种内置服务器性能较低,仅适合小规模测试,无法满足高负载场景的需求。

2. 使用 gevent 提升性能

在需要更高性能的场景中,可以选择使用 gevent 来运行 Flask 应用。gevent 是基于协程的库,适合处理 I/O 密集型任务。为了让 gevent 的协程功能生效,需要在代码的入口处调用 monkey.patch_all(),来为 Python 标准库中的 I/O 操作打补丁。例如:

from gevent import monkey
monkey.patch_all()

from flask import Flask
from gevent.pywsgi import WSGIServer

app = Flask(__name__)

@app.route("/test")
def test():
    return "Gevent running Flask!"

if __name__ == "__main__":
    server = WSGIServer(("0.0.0.0", 5000), app)
    server.serve_forever()

通过这种方式,Flask 应用可以实现更高效的并发处理,适合需要处理大量请求的场景。

3. 结合 gunicorn 和 gevent

在生产环境中,gunicorn 是一个非常流行的 WSGI Server,可以与 gevent 配合使用,既能提升性能,又能保持对内存共享变量的支持。gunicorn 会自动注入 gevent 的协程支持,无需修改应用代码。例如:

gunicorn -w 4 -k gevent -b 0.0.0.0:5000 app:app

这种方式不仅适合 I/O 密集型任务,还可以通过配置文件灵活调整工作进程数量、日志格式以及资源限制。

  • 开发阶段:内置 WSGI Server,简单易用。
  • 性能优化:使用 gevent 提升协程效率。
  • 生产环境:结合 gunicorngevent,实现高效并发处理。
Flask运行方式概览

传统进程管理:实现自动启动

在传统服务器环境中,为了确保 Flask 应用能够稳定运行并在发生故障时自动重启,通常需要使用进程管理工具来守护应用进程。以下是几种常见的进程管理方式及其特点。

1. 使用 crontab + shell 脚本

刚入行的开发者可能会选择用 crontab 配合 shell 脚本来实现基本的进程守护。这种方式通过定时检查进程状态并在进程停止时自动拉起服务。尽管这种方法简单易用,但它存在以下局限性:

  • crontab 是分钟级的任务调度工具,因此服务停止后可能需要等待一分钟才能被拉起。
  • 编写可靠的 shell 脚本需要考虑进程状态、日志管理以及僵尸进程的处理等多个方面,容易产生复杂的代码。
  • 不适合生产环境,因为缺乏更细粒度的控制和稳定性保障。

示例脚本可以定期检查应用是否运行,并在异常时重新启动:

#!/bin/bash
if ! pgrep -f "gunicorn" > /dev/null; then
    echo "Gunicorn stopped, restarting..."
    /path/to/gunicorn --config /path/to/config.py app:app
fi

尽管这种方法可以解决简单的问题,但在生产环境中并不推荐。

2. 使用 supervisor

supervisor 是一个专门的进程管理工具,可以自动启动、停止和重启服务。它配置简单,易于操作,适用于需要对多个进程进行集中管理的场景。使用 supervisor 的主要步骤包括:

  • 安装 supervisor:通常通过包管理工具安装,例如 apt-get install supervisor
  • 编写配置文件:在 /etc/supervisor/conf.d/ 中添加配置文件,定义进程的启动命令、日志路径和自动重启策略。
  • 启动服务:通过 supervisorctl 命令来启动和管理进程。

尽管 supervisor 功能强大,但它需要额外安装,并且在现代服务器环境中逐渐被 systemd 取代。

3. 推荐使用 systemd

在生产环境中,systemd 是目前最推荐的进程管理工具。作为 Linux 系统的默认初始化系统,systemd 提供了稳定性、自动重启以及灵活的配置选项。以下是使用 systemd 管理 Flask 应用的步骤:

  • 创建服务文件:在 /etc/systemd/system/ 目录下创建服务文件,如 myflaskapp.service
  • 配置服务:通过服务文件定义应用的启动命令、工作目录、环境变量以及自动重启策略。例如:
  • [Unit]
    Description=Gunicorn instance for Flask App
    After=network.target
    
    [Service]
    User=www-data
    Group=www-data
    WorkingDirectory=/path/to/app
    Environment="PATH=/path/to/venv/bin"
    ExecStart=/path/to/venv/bin/gunicorn --workers 4 --bind 0.0.0.0:8000 app:app
    Restart=on-failure
    
    [Install]
    WantedBy=multi-user.target
  • 启动服务:执行 systemctl start myflaskapp 启动服务,并通过 systemctl enable myflaskapp 设置开机自启。

systemd 的优势包括实时监控服务状态、自动重启故障服务,以及与操作系统深度集成的安全加固功能。

4. 使用 Python 虚拟环境

在传统服务器部署时,为了避免依赖冲突并保持环境的隔离性,通常会使用 Python 的虚拟环境(venvvirtualenv)。通过虚拟环境,可以确保 Flask 应用的所有依赖包都与系统环境分离。以下是创建虚拟环境的基本步骤:

# 创建虚拟环境
python3 -m venv .venv
source .venv/bin/activate

# 安装依赖
pip install -r requirements.txt

虚拟环境不仅能够提高应用的可移植性,还可以与进程管理工具结合使用,为生产环境提供更稳定的运行基础。

传统进程管理示意图

Docker 部署方案

随着容器技术的普及,使用 Docker 部署 Flask 应用已经成为现代化开发和运维的主流选择。Docker 提供了灵活的镜像构建方式以及容器化运行环境,能够显著提升应用的可移植性与管理效率。以下是使用 Docker 部署 Flask 应用的详细步骤。

1. 使用 Dockerfile 构建镜像

Dockerfile 是构建 Docker 镜像的核心文件,通过定义各个步骤来构建一个可运行的 Flask 应用镜像。在构建镜像时,安全性是非常重要的一个考虑因素,例如避免使用 root 用户运行容器。以下是一个示例 Dockerfile:

FROM python:3.11-slim

# 创建非 root 用户并安装必要依赖
RUN useradd -m appuser && \
    apt-get update && \
    apt-get install -y --no-install-recommends libpq-dev && \
    rm -rf /var/lib/apt/lists/*

WORKDIR /app

# 安装 Python 依赖
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 添加应用代码
COPY . .

# 切换到非 root 用户运行
USER appuser

# 暴露应用端口
EXPOSE 8000
CMD ["gunicorn", "--config", "gunicorn.conf.py", "wsgi:app"]

通过上述 Dockerfile,可以构建一个安全、高效的 Flask 应用镜像。在构建过程中,推荐使用非 root 用户运行容器,并清理多余的缓存文件以减少镜像体积。

2. 使用 docker-compose 管理容器配置

为了简化容器的管理,可以使用 docker-compose 来定义和运行多个服务。docker-compose.yaml 文件允许您配置环境变量、健康检查以及资源限制等重要参数。以下是一个示例配置:

version: "3.8"
services:
  flask-app:
    image: flask-app:latest
    container_name: flask_app
    ports:
      - "8000:8000"
    environment:
      FLASK_ENV: production
      DATABASE_URL: postgresql://user:password@db:5432/mydb
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
      interval: 30s
      timeout: 5s
      retries: 3
    deploy:
      resources:
        limits:
          memory: 512M
          cpus: "0.5"
        reservations:
          memory: 256M
          cpus: "0.2"
    volumes:
      - ./logs:/app/logs:rw
    read_only: true
    tmpfs:
      - /tmp:rw

通过 docker-compose 文件,可以轻松定义环境变量和端口映射,同时设置健康检查以确保服务的正常运行。此外,还可以配置内存和 CPU 的资源限制,避免单个容器占用过多系统资源。

3. 使用只读文件系统和内存卷

为了提升容器的安全性和性能,推荐使用只读文件系统和内存卷。只读文件系统能够防止容器内的应用意外修改文件,内存卷则可以加速 I/O 操作。例如:

  • read_only: true:将容器的根文件系统设置为只读,避免应用对文件的意外修改。
  • tmpfs:将临时文件存储在内存中,减少磁盘 I/O,提高性能。

这种配置不仅能够增强容器的安全性,还能够显著提高应用的运行效率。

Docker部署示意图

Kubernetes 部署方案

Kubernetes 是一种强大的容器编排工具,能够帮助开发者轻松管理和部署分布式应用。在 Flask 应用的生产环境中,Kubernetes 提供了高可用性、可扩展性和自动化管理的能力。以下是使用 Kubernetes 部署 Flask 应用的详细步骤。

1. 使用 Deployment 配置管理应用

在 Kubernetes 中,Deployment 是管理应用副本和资源限制的核心组件。它可以确保应用按照定义的副本数运行,并为每个 Pod 设置资源请求和限制。以下是一个示例配置:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: flask-app
  labels:
    app: flask-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: flask-app
  template:
    metadata:
      labels:
        app: flask-app
    spec:
      containers:
      - name: flask-app
        image: flask-app:latest
        ports:
        - containerPort: 8000
        resources:
          requests:
            memory: "256Mi"
            cpu: "100m"
          limits:
            memory: "512Mi"
            cpu: "500m"

通过上述配置,Deployment 可以确保 Flask 应用始终运行 3 个副本,并限制每个副本的内存和 CPU 使用量,避免资源耗尽或性能下降。

2. 使用 Service 暴露应用服务

Kubernetes 中的 Service 负责将应用暴露给外部用户或其他服务。它提供了稳定的访问地址,并支持负载均衡。以下是一个示例 Service 配置:

apiVersion: v1
kind: Service
metadata:
  name: flask-app-service
spec:
  selector:
    app: flask-app
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8000

通过 Service,用户可以通过端口访问 Flask 应用,而 Kubernetes 会将流量分发到运行中的 Pod。

3. 使用 Ingress 配置域名访问和限流

Ingress 是 Kubernetes 中用于管理 HTTP 和 HTTPS 请求的资源。它允许用户通过域名访问应用,并提供限流功能以保护服务免受高流量冲击。以下是一个示例 Ingress 配置:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: flask-app-ingress
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/limit-rps: "10"
    nginx.ingress.kubernetes.io/limit-burst: "20"
spec:
  rules:
  - host: flask.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: flask-app-service
            port:
              number: 80

通过 Ingress,可以配置域名 flask.example.com 指向 Flask 应用,并设置请求速率限制(如每秒 10 个请求,突发 20 个)。

4. 安全加固配置

为了提高应用的安全性,可以在 Deployment 中设置相关的安全加固配置。例如:

  • runAsNonRoot: true:禁止以 root 用户运行应用,避免潜在的安全风险。
  • readOnlyRootFilesystem: true:设置根文件系统为只读,防止意外修改。
  • 启用 Seccomp 配置:限制容器运行过程中可访问的系统调用。
  • 使用 Capabilities 删除所有不必要的权限。

这些安全配置可以有效减少攻击面,增强容器的防护能力。

Kubernetes部署示意图

橙子主题打折出售

其实我不卖,主要是这里是放广告的,所以就放了一个
毕竟主题都没做完,卖了也是坑.

购买它
所有附件
该文章没有附件.
本文为原创文章,请注意保留出处!

留言板

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

热门文章

Sql Server 部署SSIS包完成远程数据传输 本篇介绍如何使用SSIS和作业完成自动更新目标数据任务。**温馨提示:如需转载本文,请注明...SqlServer部署SSIS包完成远程数据传输 作者:Pastore Antonio
1725 浏览量
SharePoint2010升级到SharePoint2013操作手册 SharePoint2010升级到SharePoint2013操作手册目录第一章...SharePoint2010升级到SharePoint2013操作手册 作者:Pastore Antonio
1693 浏览量
C# DataTable 某一列求和 列为数字类型doubletotal=Convert.ToDouble(datatable.Com...C#DataTable某一列求和 作者:Pastore Antonio
1672 浏览量
修复moss本机访问SharePoint 401.1 HTTP错误 环境:DCServer&...修复moss本机访问SharePoint401.1HTTP错误 作者:Pastore Antonio
1660 浏览量
从0开始搭建SQL Server AlwaysOn 第三篇(配置AlwaysOn) 这一篇是从0开始搭建SQLServerAlwaysOn的第三篇,这一篇才真正开始搭建Alway...从0开始搭建SQLServerAlwaysOn第三篇(配置AlwaysOn) 作者:Pastore Antonio
1626 浏览量