ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Flask应用生产部署:Gunicorn与WSGI服务器配置实战指南

Flask应用生产部署:Gunicorn与WSGI服务器配置实战指南 服务员这个比喻我觉得特别贴切。你想想Flask自带那个开发服务器就像个家庭小灶自己一个人炒菜家里来了三五个客人还能应付要是哪天办个喜事一下子来几十桌那后厨不得直接瘫掉Gunicorn干的事儿就是给你请来一支专业的服务团队——有人专门负责在后厨炒菜跑你的Python代码有人专门负责把菜端到客人桌上收发HTTP请求还有人盯着流量高峰调度人手管理worker进程。说白了它是一个生产级的WSGI HTTP服务器专为Python Web应用服务尤其是Flask这种纯同步框架配上Gunicorn之后才能扛住真实世界的并发访问。这篇文章不绕弯子直接讲清楚Gunicorn怎么和Flask配合、worker怎么选、数量怎么算、部署怎么落地以及你跑“农产品价格数据可视化”这类Flask应用时最容易踩的坑。我见过太多人本地跑Flask应用顺顺溜溜一丢到云服务器上就各种超时、502、内存暴涨最后怀疑人生。其实问题八成不在你的代码逻辑而在你还让Flask那个开发服务器在裸奔。这篇文章适合刚学会Flask、正准备把应用部署上线的朋友也适合已经部署了但性能始终不理想、想弄明白Gunicorn配置背后原理的人。我会用一套完整的部署方案贯穿全文从为什么到怎么做再附带排查实录保证你读完能直接照着操作。1. 为什么Flask“自带服务器”不能直接上生产先说结论Flask自带的开发服务器werkzeug.serving设计目标就是给开发者调试用的不是给生产环境扛流量用的。它不是不稳定而是压根没往那个方向设计。1.1 开发服务器的局限到底在哪里Flask里你敲下app.run()启动的其实是Werkzeug内置的一个简易HTTP服务器。它有几个硬伤单进程、单线程模型默认情况下它同一时间只能处理一个请求。虽然Werkzeug也支持threadedTrue这种参数但本质上还是在一个进程内做线程切换遇到CPU密集型的视图函数时照样堵成一锅粥。没有进程管理能力它不会在你代码抛异常时自动重启不会在内存泄漏时帮你回收更不会在流量突增时动态增加处理能力。安全问题开发服务器自带调试器Debugger这个调试器允许浏览器端执行代码通过PIN码认证。一旦暴露到公网等于把服务器后门钥匙挂在门口。性能上限很低纯Python实现的WSGI服务器吞吐量天花板摆在那里。我实测过一个最简单的Flask接口开发服务器压到每秒一两百个请求就崩了而同样代码换到Gunicorn轻轻松松上千。1.2 生产环境需要的是什么生产环境的HTTP服务链路标配是三件事接收请求、执行应用逻辑、返回响应。听起来简单但放到公网上就变成另一回事了。你要处理慢连接客户端断断续续发数据、慢客户端用户网速差、超大请求体、超时控制、并发调度、静态文件、HTTPS终止等等。你当然可以全用Python写一套出来但这不是重复造轮子的问题而是安全性和稳定性问题。行业里早就标准化了应用框架Flask只管业务逻辑WSGI服务器Gunicorn管进程调度和请求分发反向代理Nginx管静态文件、负载均衡和安全防护。各司其职谁也别越权。所以我给你的第一个建议是别把app.run()用在生产上这不是什么“高手的习惯”而是基本底线。1.3 关于“服务器”和“服务员”的角色对话回到“服务员团队”这个比喻Flask是后厨负责炒菜。你写的视图函数就是一道道菜谱。WSGI服务器Gunicorn是前厅经理负责安排服务员接单、上菜并把后厨炒好的菜端给客人。Nginx是门口负责拉客和维持秩序的大堂保安帮你把不怀好意的人挡在外面同时把好酒好菜用最快的通道送进去。一个后厨再强没有前厅和保安的配合店面开大了照样歇菜。Gunicorn就是那个帮你把Flask后厨和前厅之间的流程理顺的角色。2. Gunicorn的核心工作原理看懂“服务员团队”的分工理解Gunicorn最关键的是搞清楚它和Flask之间的那条“通道”——WSGI协议。2.1 WSGI协议Flask和Gunicorn之间的“上菜通道”WSGIWeb Server Gateway Interface是Python Web应用的事实标准协议。它的作用就是规定服务器Gunicorn怎么把HTTP请求转成Python能看懂的对象以及Python应用Flask处理完之后怎么把响应再转回HTTP格式。这个过程你可以理解成——服务员Gunicorn和后厨Flask之间有一套固定的话术。服务员在菜单上写下客人的点单HTTP请求后厨照着单子炒菜处理业务逻辑炒好了放到出餐口返回一个响应对象服务员再端给客人发送HTTP响应。这套话术WSGI协议保证了Gunicorn和Flask不需要互相了解内部实现只要双方都遵守WSGI就能无缝配合。不管你是Flask、Django还是其他WSGI框架Gunicorn都一视同仁。2.2 Gunicorn的“服务员团队”架构拆解Gunicorn的架构非常经典它有三个层次组件类比角色具体职责Master进程餐厅经理不直接接待客人负责管理整个团队。接收外部信号如重启、关闭、fork出Worker进程、监督Worker健康状态、对应访问日志和错误日志Worker进程一线服务员真正处理请求的进程。每个Worker同时只能处理一个请求sync模式下或者并发处理多个请求异步模式下Arbtier人力资源专员藏在Master内部的调度核心决定什么时候需要增派人手、什么时候可以削减人手Master进程是整个团队的大脑。它不做业务只做管理。你还记得那句经典的Linus名言“Talk is cheap, show me the code”吗在Gunicorn这里变成了“Master不写代码只是代码的守护者”。Master会定期检查每个Worker活没活着如果某个Worker处理请求时挂了比如段错误Master会立刻拉起一个新的Worker顶上保证你的服务不会因为一个Worker崩溃就整体宕机。2.3 请求从进入到返回整个流程走一遍假设你部署了一个“农产品价格数据可视化”Flask应用用户手机上点开图表页面请求价格的接口。这个过程是这样的用户的浏览器向服务器IP的80端口发起HTTP请求通常是经过Nginx转发到Gunicorn的8000端口。Gunicorn的Master进程在8000端口监听通过socket bind收到连接后把它交给一个空闲的Worker进程。Worker进程通过WSGI协议调用你的Flask应用Flask框架解析request对象匹配URL路由执行对应的视图函数比如查数据库拿今天西红柿的价格。数据在视图函数里被处理成JSON返回给Flask框架Flask再构造一个response对象交给Worker进程。Worker进程把response转成HTTP响应数据通过TCP连接返回给浏览器。这一个流程下来你会注意到一个关键点Worker在收到请求到返回响应这段过程中是完全被这个请求占用的。如果请求特别慢比如数据库查询要3秒那这一个Worker在这3秒内就服务不了任何人。这就是为什么Worker数量和服务模式的选择如此重要也是下一节要重点展开的内容。3. Worker类型与数量服务员怎么配才扛得住流量Gunicorn的配置里最让人头疼也最影响性能的就是worker_class和workers这两个参数。我见过无数人在这上面踩坑配置不对压力上来直接雪崩。3.1 sync worker 和异步worker怎么选Gunicorn默认的worker类型是sync同步。一个sync Worker同一时间只能处理一个请求。你可以把它想象成一个服务员一桌客人没吃完他就一直在旁边守着不能去接待别的客人。sync模式的问题是如果你的应用里有I/O操作比如数据库查询、调用第三方API、磁盘读文件那么这些等待时间全都白白浪费了。一个请求等2秒这一个Worker在2秒内就是空转资源利用率极低。那怎么办两种方案方案一增加Worker数量多招几个服务员有多少个Worker就能同时处理多少个请求。但每个Worker是一个独立的进程有独立的内存空间所以数量不能无限加受限于服务器的CPU核数和内存。方案二改用异步Worker让一个服务员同时照顾多桌客人Gunicorn支持gevent和eventlet这两种异步Worker类型。它们的原理是在一个Worker进程内通过协程greenlet实现并发。当一个请求在等待数据库返回时Worker能立刻切换到另一个请求继续处理。一个Worker就可以同时挂在成百上千个连接上只要不是CPU密集型任务性能提升非常可观。这里我要强调一个重点如果应用本身是CPU密集型的比如做大量计算、图像处理异步Worker并没有帮助反而因为协程切换带来额外开销。什么时候要用异步Worker你的视图函数里有大量I/O等待比如查数据库、调外部接口、读写文件。我做的农产品价格数据可视化项目就属于这种——每个请求都要去查数据库聚合价格数据数据库查询能快到哪里去呢就是I/O密集型的典型场景。实际项目中我推荐优先用gthread线程模式。Gunicorn还支持一种gthreadWorker它在每个进程内部使用线程池来处理请求。如果你的应用已经用了很多第三方库其中有些不是协程安全的gthread可能比gevent更稳妥。纯手动挡选sync追求极致性能选gevent要稳中求快选gthread这就是我的选型建议。3.2 Worker数量的计算公式到底怎么算Worker数量没有一个绝对正确值但业界有一个公认的参考公式主从模式syncworkers (2 × CPU核数) 1 异步模式gevent/eventletworkers CPU核数 线程模式gthreadworkers CPU核数每worker线程数 若干为什么是“2 × CPU核数 1”这个公式是从经验中总结出来的。Web服务的瓶颈通常不在CPU而在I/O。多出1个Worker是为了在CPU调度间隙里总有Worker能被调度到不至于出现CPU空转。如果你的服务器是2核那sync模式下5个Worker是比较稳妥的起点。但要注意Worker越多内存开销越大。每个Worker都要加载一遍你的Flask应用和所有依赖库。如果你的应用光是加载就把内存吃到200MB那4核服务器上9个Worker光基础内存就是1.8GB。小内存机器先把Worker数量往下调宁可让worker少一点也不能让系统内存爆掉进入Swap再白白拖垮性能。我自己的一个实用方法是从公式算出的数字开始然后用压测工具比如wrk或者ab看随Worker数变化的吞吐量曲线找到拐点。那个拐点就是你这台机器的最佳配置。如果懒得压测记住云上2核4G的小机器sync模式下5个Worker或gevent模式下2个Worker基本够大多数Flask应用起步了。3.3 超时与keep-alive的细节痛点还有一个经常被忽略但极其影响用户体验的参数timeout默认30秒。如果处理一个请求超过30秒Gunicorn会把这个Worker杀掉并重启新的Worker至于原因问题的本质是Gunicorn认为Worker可能已死锁杀掉了事。农产品价格数据可视化这种应用如果数据量大前端导出Excel或绘制大图耗时较长就可能超过30秒用户会看到一个空数据页面逻辑完全没执行完却在日志里发现“Worker timed out”。处理办法有两个要么把timeout调大比如设为60或120要么把耗时操作放到后台任务队列Celery去跑不要让HTTP请求一直挂着。我强烈推荐后者HTTP请求保持太久本来就是一种坏味道。还有个参数叫keepalive默认是2秒。它控制的是HTTP持久连接的空闲时间。现在前端写异步请求都用fetch或axios浏览器和服务器之间往往短时间内会发送多个请求合理拉长keepalive能减少TCP握手次数降低延迟。我一般设为5秒已经能覆盖绝大多数场景了。4. 部署实操把Flask应用交给Gunicorn现在咱们来点真刀真枪的。这一节我会给你一套完整可用的部署流程涵盖安装、启动、配置文件和守护进程管理照着抄就行。4.1 安装与基础启动假设你的Flask应用目录叫flask_app入口文件是app.py里面有一个app Flask(__name__)的实例。先安装Gunicorn。强烈建议在你的虚拟环境venv里装别用全局环境cd /path/to/flask_app python3 -m venv venv source venv/bin/activate pip install gunicorn启动一个最基本的服务监听8000端口只需要一行命令gunicorn -w 4 -b 0.0.0.0:8000 app:app注意这里最后的app:app含义是“模块名:变量名”。app.py模块里有一个叫app的Flask实例Gunicorn就是通过这个参数找到你的应用的。如果你的入口文件名是wsgi.pyFlask实例名为application那就要写成wsgi:application。我遇到过很多人把这里写错不停报“Cannot import module”其实就是路径和名字对应不上。还有个小技巧如果你嫌每次敲参数麻烦可以把所有配置写进一个gunicorn.conf.py文件然后只需要gunicorn -c gunicorn.conf.py app:app就够了。4.2 配置文件完整示例可直接抄这是我沉淀过很长时间的一份配置文件我在多个生产项目里用过稳得很# gunicorn.conf.py import multiprocessing # 绑定的IP和端口一般只对内网监听前面挂Nginx不建议直接对公网暴露 bind 127.0.0.1:8000 # 工作目录 chdir /path/to/flask_app # worker数量和类型 workers multiprocessing.cpu_count() * 2 1 worker_class gevent # 如果你的代码是I/O密集型的推荐这个保守用sync # 每个worker的并发数gevent模式下有效 worker_connections 1000 # 超时设置 timeout 60 # 超过60秒杀worker重启看你的业务来定 graceful_timeout 30 # 平滑重启时给worker的收尾时间 keepalive 5 # 长连接空闲时间 # 进程名和日志 proc_name flask_app_gunicorn accesslog /var/log/gunicorn/access.log errorlog /var/log/gunicorn/error.log loglevel info注意千万不要让Gunicorn直接对外监听公网IP的8000端口。你对外暴露的应该是Nginx的80端口或443端口Nginx再把请求转发到Gunicorn的8000。这样做的原因有三个Nginx处理静态文件、缓存、HTTPS证书比Gunicorn强太多。Nginx有连接缓冲能抵御慢速攻击Gunicorn直接暴露公网压力很大。隔离设计更安全Gunicorn只在内网通信不存在的公网入口攻击面就少了一块。日志目录记得预先创建否则Gunicorn起不来的。很多人配置了accesslog路径但目录不存在启动直接报错看日志又一脸懵。4.3 用systemd守护Gunicorn让服务自己活生产环境里你不能指望人肉盯着进程查活着没。Linux服务器上标准的做法是用systemd管理Gunicorn进程由它负责开机自启、崩溃重启、日志收集。创建文件/etc/systemd/system/flask_app.service[Unit] DescriptionGunicorn instance for Flask App Afternetwork.target [Service] Userwww-data Groupwww-data WorkingDirectory/path/to/flask_app EnvironmentPATH/path/to/flask_app/venv/bin ExecStart/path/to/flask_app/venv/bin/gunicorn -c /path/to/flask_app/gunicorn.conf.py app:app Restartalways RestartSec10 [Install] WantedBymulti-user.target这段配置的要点User/Group建议设置成专门的低权限用户比如www-data千万别用root跑Web应用万一被攻击root权限被拿走那灾难级了。Restartalways表示只要进程退出systemd就自动拉起间隔10秒。这保证了即使GunicornMaster进程意外挂了服务也能自动恢复。Afternetwork.target确保网络已经就绪再启动服务避免开机时绑定端口失败。启动和自启动命令sudo systemctl daemon-reload sudo systemctl start flask_app sudo systemctl enable flask_app sudo systemctl status flask_app这几条命令跑完之后你的Flask应用就有了一个像样的生产级进程管理方案了。后面想重启更新代码一行sudo systemctl restart flask_app搞定。5. Gunicorn Nginx前厅与后厨的黄金组合很多新手会疑惑既然Gunicorn本身就能处理HTTP请求为啥还要再套一层Nginx这不是多此一举吗看起来是多了个中间层实际上这个“中间层”的价值非常大。5.1 为什么不直接暴露Gunicorn端口你想一个场景一个用户浏览器请求的是“农产品价格数据可视化”页面的首页首页里有图片、CSS、JavaScript这些是静态文件。如果你只用一个Gunicorn那么每个静态文件请求都会去压一遍你的Flask进程每个请求都要走一遍Python代码、定时任务、数据库查询——明明这些文件的内容根本不需要动态改动白白浪费计算资源。Nginx在这里就像一个高效的快递分拣员看到请求是静态文件直接从自己磁盘上的Nginx缓存目录里返回压根不打扰后面的Gunicorn。静态文件请求占比越高这一层缓存的收益就越大。我做过压测对比纯静态资源Nginx的吞吐量能到每秒几万Gunicorn的Flask应用扛到每秒一千出头就差不多该削峰了何况Web页面里的静态资源请求往往是最多的。另一个重要作用是负载均衡和连接管理。Nginx默认一个客户端可以有多个并发连接而Gunicorn的Worker是有限的。Nginx可以帮Gunicorn挡掉很多无效连接它和Gunicorn之间用的其实是持久连接上游keepalive大大减少握手次数。最后一个关键点是HTTPS终结。SSL/TLS证书校验、加解密这些操作挂在Nginx上最合适。Nginx处理这种计算是用C语言做的性能比Python高好几个量级。你只需要把证书配置在Nginx层后面转发给Gunicorn的流量用明文HTTP走内部网络就行既安全又高效。5.2 Nginx配置示例含Gunicorn反向代理一个最简但完整的Nginx站点配置直接放/etc/nginx/sites-available/flask_appserver { listen 80; server_name your_domain.com; # 静态文件直接由Nginx处理不走Flask location /static/ { alias /path/to/flask_app/static/; expires 30d; add_header Cache-Control public; } # 其他所有请求转发给Gunicorn 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; proxy_set_header X-Forwarded-Proto $scheme; proxy_connect_timeout 30s; proxy_read_timeout 60s; } }这段配置有几个地方需要特别说明proxy_set_header里把真实客户端IP传给了后端。没有这几行你的Flask应用拿到的所有请求来源IP都会是127.0.0.1Nginx的地址不管你的日志统计也好、防刷限流也好全都废掉了。proxy_read_timeout 60s要和Gunicorn的timeout参数匹配并且稍微大一点。如果Nginx这边超时设定得比Gunicorn还短会造成Nginx先断开连接Gunicorn那边还在处理DB查询白跑了。Flask应用里凡是生成绝对URL的地方要用配置项PREFERRED_URL_SCHEME或读取X-Forwarded-Proto否则即使你用HTTPS访问页面Flask生成的链接也可能是http://。5.3 静态文件该放谁名下还有个小细节。如果你用Flask的send_from_directory来做文件下载或者用url_for(static, filename...)的方式来管理静态资源那这个“静态文件”到底归Nginx管还是归Gunicorn管我的习惯是凡是经过Nginx的静态资源路径要统一收敛到/static/前缀下Nginx用alias指到实际目录。这样一来CSS/JS/图片这些永不改动或很少改动的文件干脆就跟Flask没关系了。后端接口返回JSON数据时前端的图表库比如ECharts直接用相对路径/static/xxx.js去加载一切都走Nginx利索得很。如果你改了前端资源但因为浏览器缓存没生效就在Nginx的location /static/配置里加上add_header Cache-Control no-cache;做临时处理或干脆在文件名后加版本参数app.js?v20250212这样比清缓存痛快得多。6. 常见问题与排查实录Gunicorn部署的典型事故部署Gunicorn过程中我踩过不少坑有些坑很隐蔽但只要你理解了Gunicorn的运作机制就都能排查到。这一节我挑四个最高频的典型事故来讲。6.1 “Connection Refused”连接被拒症状浏览器访问Nginx报502Nginx错误日志里全是connect() failed (111: Connection refused) while connecting to upstream。排查步骤先确认Gunicorn进程活着没ps aux | grep gunicorn一行输出都没有说明服务挂了。看systemd状态systemctl status flask_app。确认Gunicorn监听端口对不对netstat -tlnp | grep 8000。如果没监听大概率是配置文件里bind或worker_class写错了导致启动失败查看/var/log/gunicorn/error.log。权限问题也常见。比如Gunicorn用www-data用户启动这个用户对应用目录没有读权限chdir失败进程根本没起来。对着目录chown -R www-data:www-data /path/to/flask_app。防火墙拦截。很多云主机默认安全组规则只开了80忘了放通Nginx到Gunicorn的127.0.0.1回环通信。这种一般用ss -tlnp能看到监听但外部连接过不来。生产环境完全可以让内部不同端口但前提是安全组放行。6.2 “Worker timed out”超时被杀的谜团这个我前面提过一嘴现在展开讲。日志里出现[CRITICAL] WORKER TIMEOUT (pid:xxx)很多人的第一反应是代码死循环了但更多时候是视图函数执行时间超过了timeout参数。我之前做过一个农产品价格数据可视化接口用户选了某个月份看历史价格曲线后台要查一个大数据表再聚合计算高峰期耗时能飙到40秒。而Gunicorn默认timeout 30于是Worker被Master杀掉——注意是杀掉整个Worker进程如果这个Worker正处理着其他请求那些请求也会一并被终止。排查思路看请求日志定位当前正在执行的URL。用time curl或ab测量这个接口到底耗时多少。如果接口确实是“慢而稳”调高timeouttimeout 90同时把Nginx的proxy_read_timeout也相应调大。更优雅的做法是把这种耗时任务丢到后台异步队列Celery Redis里去前端先返回“处理中”轮询结果。这才叫治本。我个人很反感纯粹调高大timeout来解决问题的做法。除非你确知某个接口偶尔会慢否则每个长期存活的慢请求就像占着茅坑不拉屎它会拖垮整个服务。把慢任务拆出去是对Gunicorn“服务员团队”的尊重大家才能把手头的活干完。6.3 高并发下内存飙到 “Out of Memory”很多云服务器是2核4G的如果你用 sync worker 跑workers 2 * 2 1 5每个Worker加载Flask应用加上数据库连接池大概内存占用是150-300MB五个就是1GB多听起来还好。但如果你不小心把worker_class配成了gevent并且没有限制worker数量直接写了workers 8那8个进程加载下来内存分分钟爆掉。解决办法优先减少workers数量用ps -o rss,cmd -p pid看每个worker的实际内存占用。增设max_requests参数。每个Worker处理一定数量请求后就自动重启释放内存碎片。这在处理旧版本代码内存泄漏问题时很有效max_requests 1000 max_requests_jitter 100 # 加一个抖动防止所有worker同时重启这个参数我常年开着原理是“这样每个Worker处理完1000到1100个请求后自然重启内存像潮汐一样有进有出不会越积越高”。注意抖动的意义避免所有Worker同时满负载重启。6.4 日志里莫名出现许多进程挂掉如果你开了debug级别的日志Gunicorn会记录很多GET / 200的访问日志全堆到errorlog里。其实accesslog和errorlog是两个日志通道访问日志要单独开错误日志也别直接设为debug那是排查问题用的生产环境设成info就够了。还有个容易被忽视的问题Gunicorn默认是同步写日志的日志量大时会把进程拖慢。建议用系统自带的journalctl或交给logrotate定期切割别让日志文件无限增长。反正一行日志几KB几千个请求下来就是几十兆了时间长了磁盘会满的。7. 农产品价格数据可视化场景Gunicorn部署实战复盘说你呢做“农产品价格数据可视化-Flask”的朋友。这种数据可视化应用我有幸做过一个类似的挑几个实在的坑讲一讲。数据怎么喂给前端。可视化平台往往要同时展示多种数据都是图表库ECharts、Plotly或前端自绘的Canvas在渲染。图表渲染靠的是JSON数据接口这些接口天然是I/O密集的从数据库读价格历史、读产地分布统计、读环比涨跌。所以呢Gunicorn的worker_class推荐直接用gevent。我实测下来在同样的2核4G机器上import同一个大数据库sync模式下接口响应时间在5%-10%的时候明显劣化而gevent模式还能维持不错的稳定性。缓存一定要做。同一种农产品的价格数据不可能每秒都在变本地Redis缓存一下TTL设个60秒绝大多数请求连数据库都不用查Gunicorn处理起来飞快。这个优化能让你把Worker数量直接减半省下来的内存可以给数据库更大的缓冲池。慢查询接口的重灾区是聚合计算。比如用户选最近30天所有省份的番茄均价曲线如果直接GROUP BY date去库里查询一旦数据量上到几十万行查询时间不容乐观。这时候你要么在数据库里提前物化好统计表要么在Flask里加个进程内缓存functools.lru_cache或者用上面说的异步队列异步生成结果缓存起来。记住Gunicorn负责让你应用的核心流程稳定但数据库的索引和查询优化必须提前做。不然就算Gunicorn给你一百个Worker每个Worker都在等数据库慢慢吐数据也是白搭。你先解决了慢查询再考虑Worker数量效率和效果都积极得多。数据接口幂等性。可视化页面经常被前端定时轮询比如每5秒拉一次最新价格。如果你的接口不是幂等的每次请求都产生副作用或重复计算那Gunicorn并发地处理同一个URL的多个请求时资源浪费巨大。好消息是Gunicorn天生就是并发环境下跑的你只要保证接口是纯查询、无副作用配合Redis缓存压力轻松消解。最后一个小技巧接上Gunicorn后处理慢客户端问题的是一个参数graceful_timeout。它控制Worker平滑退出时等待当前请求完成的时间。如果前端在下载一个大体积的CSV比如价格明细导出用户突然走了连接断了Gunicorn需要判断一个断掉的连接什么时候该释放。设个30秒别让Worker无限等下去比设600秒更稳我就是这样一步步把整个数据可视化服务的稳定性调起来的。Gunicorn这东西说实话你用好了之后它就像一个特别可靠的后勤团队你几乎感觉不到它的存在但你心里清楚自己的Flask应用从里到外是真正被稳住的了。我踩过的那些坑你现在知道了基本就能少走一大半弯路。后面如果你的应用流量涨到需要多台机器跑时Gunicorn作为“服务员团队”的定位依然成立你再在Nginx那层加个负载均衡就顺理成章了但架构的底座还是一致。希望这份指南能帮你把自己的Flask应用顺顺利利地送上生产环境并且在它跑得很稳的时候不给这段部署经历留下什么跌宕起伏的错觉。
返回列表