Flask 生产部署指南:使用 uWSGI 运行 WSGI 应用
Flask 生产部署指南使用 uWSGI 运行 WSGI 应用【免费下载链接】flaskThe Python micro framework for building web applications.项目地址: https://gitcode.com/gh_mirrors/fl/flask本文以 Flask 官方部署文档 docs/deploying/uwsgi.rst 为主体介绍如何使用 uWSGI 这一高性能编译型 WSGI 服务器来运行 Flask 应用涵盖 pyuwsgi 与 uwsgi 两种安装方式、--http/--master/-p/-w等核心启动参数、应用工厂模式的wsgi.py入口写法、对外绑定与反向代理的取舍以及基于 gevent 的异步 worker 配置。读完本文你将能独立完成一个 Flask 应用从虚拟环境搭建到 uWSGI 生产启动的完整流程并理解每一步背后的原理与安全注意事项。uWSGI 与 Flask为什么选择它Flask 是一个 WSGI应用它本身并不内置适合生产的 HTTP 服务器——内置的flask run开发服务器只用于本地开发官方部署文档 docs/deploying/index.rst 明确强调Do not use the development server when deploying to production. It is intended for use only during local development. It is not designed to be particularly secure, stable, or efficient. 生产环境需要用独立的 WSGI服务器来承接 HTTP 请求将其转换为 WSGI environ 传给 Flask再把 Flask 的响应转回 HTTP。uWSGI 就是这样一个成熟的生产级 WSGI 服务器。官方文档对其定位概括如下性能好uWSGI 是编译型程序compiled program执行效率高可以支撑很高的性能需求配置复杂除基础用法外它的配置体系庞大、选项极多对初学者而言学习曲线较陡平台限制不支持 Windows但可在 WSL 下运行安装门槛某些安装路径下需要编译器。本文只覆盖运行 uWSGI 的基础操作更丰富的特性请以 uWSGI 自身文档为准。安装pyuwsgi 与 uwsgi 的选择uWSGI 有若干种安装方式官方推荐的首选是安装pyuwsgi包——它为常见平台提供预编译的 wheel无需本机编译器即可安装。但需要注意pyuwsgi 的预编译 wheel 不包含 SSL 支持。生产环境中的 SSL/TLS 通常改由前置反向代理如 Nginx、Apache来终结因此这一限制一般不影响使用。安装流程先创建虚拟环境、安装你的应用再安装pyuwsgi$ cd hello-app $ python -m venv .venv $ . .venv/bin/activate $ pip install . # install your application $ pip install pyuwsgi如果你的机器上有可用的编译器则有两个替代方案可以获得包含 SSL 支持的安装直接安装源码编译的uwsgi包$ pip install uwsgi或者强制从 sdist 源码包构建pyuwsgi跳过预编译 wheel$ pip install --no-binary pyuwsgi pyuwsgi两条命令都会在本机编译从而带上 SSL 支持。基础运行让 uWSGI 启动 HTTP 服务器并导入应用uWSGI 最基础的运行方式是让它同时扮演 HTTP 服务器与 WSGI 服务器用--http监听端口用-w指定要导入的 WSGI 应用对象。假设你的项目根目录下有一个hello.py里面定义了模块级变量app一个Flask实例那么运行$ uwsgi --http 127.0.0.1:8000 --master -p 4 -w hello:app *** Starting uWSGI 2.0.20 (64bit) on [x] *** *** Operational MODE: preforking *** mounting hello:app on / spawned uWSGI master process (pid: x) spawned uWSGI worker 1 (pid: x, cores: 1) spawned uWSGI worker 2 (pid: x, cores: 1) spawned uWSGI worker 3 (pid: x, cores: 1) spawned uWSGI worker 4 (pid: x, cores: 1) spawned uWSGI http 1 (pid: x)各启动参数的含义参数作用--http 127.0.0.1:8000在 127.0.0.1 的 8000 端口启动一个内置 HTTP 服务器对外提供 HTTP 访问--master启用标准的 worker 管理器master 进程由它统一管理 worker 生命周期-p 4启动 4 个 worker 进程官方建议的起始值可设为CPU * 2再结合压测调优-w hello:app告诉 uWSGI 如何导入应用hello是模块名app是该模块中的 WSGI 应用对象从启动日志可以看到典型的 preforking 模型1 个 master 进程pid: x管理 4 个 worker 进程每个 worker 1 个 core外加 1 个内置 HTTP 进程http 1。请求先到达 HTTP 进程再被转发给 worker 处理。应用工厂模式先写 wsgi.py 入口如果你的应用采用应用工厂application factory模式——把应用对象的创建封装在create_app()函数里——那么-w hello:app这种直接导入模块级app对象的方式就行不通了因为此时模块里还没有现成的app对象。解决办法是新建一个极小的wsgi.py入口文件在模块导入时调用工厂并生成应用实例# wsgi.py from hello import create_app app create_app()然后让 uWSGI 指向这个入口$ uwsgi --http 127.0.0.1:8000 --master -p 4 -w wsgi:app这条工厂 独立入口文件的部署模式在当前仓库中有完整的真实样例教程项目 examples/tutorial/flaskr/init.py 定义了标准的create_app(test_configNone)工厂内部完成配置加载from_mapping/from_pyfile、创建 instance 目录、注册db、注册auth与blog蓝图、添加index路由规则测试应用 tests/test_apps/helloworld/wsgi.py 则展示了最精简的入口写法——一行from hello import app即可把模块级应用对象暴露给 WSGI 服务器导入。工厂模式在 docs/patterns/appfactories.rst 中有详细讲解把Flask(__name__)放进函数后同一进程内可以按不同配置创建多个应用实例便于测试与多实例部署扩展对象如 Flask-SQLAlchemy 的db应先在模块级创建、再由db.init_app(app)绑定避免把应用特定状态存到扩展对象上。对外绑定端口、权限与反向代理不要用 root 运行、不要直接绑定 80/443本文给出的配置不应以 root 身份运行 uWSGI——否则你的应用代码也会以 root 权限执行存在严重安全隐患。但这样一来uWSGI 就无法直接绑定 80 或 443 等特权端口。官方给出的推荐拓扑是在 uWSGI 前面再放一个反向代理例如 docs/deploying/nginx.rst 或 docs/deploying/apache-httpd.rst 中介绍的方式。uWSGI 对Nginx uWSGI与Apache mod_proxy_uwsgi有专门的优化集成而非走普通 HTTP 代理这类配置细节超出本文范围可查阅 uWSGI 文档。以 Nginx 为例docs/deploying/nginx.rst 给出的反向代理配置如下——假设 WSGI 服务器监听在本机http://127.0.0.1:8000server { listen 80; server_name _; location / { proxy_pass http://127.0.0.1:8000/; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Prefix /; } }代理把真实请求信息通过X-Forwarded-*头传给后端。此时必须让 Flask 信任并使用这些头否则应用会把所有请求都当作来自本机。做法是在应用中包裹 Werkzeug 的ProxyFix中间件详见 docs/deploying/proxy_fix.rstfrom werkzeug.middleware.proxy_fix import ProxyFix app.wsgi_app ProxyFix( app.wsgi_app, x_for1, x_proto1, x_host1, x_prefix1 )安全提示ProxyFix只应在确实处于反向代理之后时使用且必须如实填写链路中实际设置各头的代理层数x_for1表示只有 1 层代理设置X-Forwarded-For。入站头是可以被伪造的配置错误会引入安全漏洞。直接对外监听的用法如果不使用反向代理可以绑定到所有外部 IP 的非特权端口$ uwsgi --http 0.0.0.0:8000 --master -p 4 -w wsgi:app需要明确两点0.0.0.0是监听所有网卡地址的绑定地址不是可访问地址浏览器里要输入具体的 IP如http://你的服务器IP:8000使用反向代理时不要用0.0.0.0对外监听否则客户端可以绕过代理直连 uWSGIX-Forwarded-*头与ProxyFix的信任模型就会被破坏。异步扩展用 gevent 承载大量并发长连接uWSGI 默认的sync worker对大多数场景是合适的。但当应用需要同时维持大量、长连接、高并发的连接时uWSGI 提供了基于 gevent 的异步 worker 模式。先明确概念边界这里的 gevent 异步不是Python 的async/await也不是ASGI 服务器规范。它是通过 greenlet 对 Python 标准库做 monkey-patch在解释器层面实现并发调度代码里不需要写任何async def/await。关于如何在应用代码中启用 gevent参见 docs/gevent.rst需要在模块最顶部尽早调用import gevent.monkey gevent.monkey.patch_all()uWSGI 侧只需增加--gevent参数并指定并发数这里为 100$ uwsgi --http 127.0.0.1:8000 --master --gevent 100 -w wsgi:app *** Starting uWSGI 2.0.20 (64bit) on [x] *** *** Operational MODE: async *** mounting hello:app on / spawned uWSGI master process (pid: x) spawned uWSGI worker 1 (pid: x, cores: 100) spawned uWSGI http 1 (pid: x) *** running gevent loop engine [addr:x] ***对比两次启动日志可以看到模式差异sync 模式输出Operational MODE: preforking每个 worker 只有 1 个 coregevent 模式输出Operational MODE: async日志中的cores: 100即--gevent 100指定的并发 greenlet 数量并出现running gevent loop engine字样表明 gevent 事件循环已接管 worker。版本要求与 docs/gevent.rst 一致使用 gevent 时要求greenlet 1.0使用 PyPy 时要求PyPy 7.3.7。另外需要注意 gevent 与 Flask 内建 asyncio 支持并不友好兼容如需在同一应用中混用需要覆写flask.Flask.async_to_sync把异步函数调度到 gevent 中的 asyncio 事件循环上具体示例见 docs/gevent.rst 的 Combining with async/await 一节。部署位置与后续步骤uWSGI 属于 docs/deploying/index.rst 中列出的自托管 WSGI 服务器方案之一。该页同时说明WSGI 服务器虽自带 HTTP 能力但在其前面加一台专用 HTTP 服务器作为反向代理往往更安全、更高效、能力更强常见的托管平台如 PythonAnywhere、Google Cloud Run 等也大多基于这类 WSGI 服务器且通常需要配合 docs/deploying/proxy_fix.rst 使用。完整的部署路径可以串联为按 docs/patterns/appfactories.rst 组织应用工厂 → 用wsgi.py暴露应用实例 → 安装pyuwsgi并启动 uWSGI → 视需要在前方配置 Nginx/Apache 反向代理并套用ProxyFix→ 流量大或长连接多时切换--geventworker。每一步的取舍编译安装 vs 预编译、特权端口 vs 非特权端口、sync vs async都对应着生产环境中的真实考量这也是本文希望帮你建立的核心判断力。【免费下载链接】flaskThe Python micro framework for building web applications.项目地址: https://gitcode.com/gh_mirrors/fl/flask创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →