长轮询在Flask中需禁用Werkzeug开发服务器,改用Gunicorn+gevent或Uvicorn+ASGI;避免time.sleep(),改用queue.Queue.get(timeout=...)或asyncio.Queue配合超时控制,并同步调高Nginx proxy_read_timeout等中间层超时参数。

长轮询请求在 Flask 中怎么写才不会超时?
Flask 默认的开发服务器(Werkzeug)是单线程、同步阻塞的,time.sleep() 或 queue.get() 这类操作会直接卡住整个进程,导致后续请求排队等待。生产环境用 Gunicorn + gevent 或 Uvicorn + ASGI 才能真正支持并发长轮询。
- 必须禁用 Werkzeug 的超时干扰:启动时加
--timeout 300(Gunicorn)或设置server_header=False(Uvicorn)只是表象,关键是底层要能挂起连接而不占线程 - 不要用
while True轮询检查状态,改用线程安全的queue.Queue或asyncio.Queue配合get(timeout=...) - 客户端发起的请求必须带
Connection: keep-alive,服务端响应头里别主动加Connection: close
from flask import Flask, request, jsonify
import queue
import threading
<p>app = Flask(<strong>name</strong>)
msg_queue = queue.Queue()</p><p>@app.route('/events')
def long_poll():
try:
msg = msg_queue.get(timeout=30) # 阻塞最多30秒
return jsonify({'data': msg})
except queue.Empty:
return jsonify({'data': None}), 204</p>客户端反复 408 Request Timeout 怎么排查?
408 大概率不是你的代码问题,而是中间层(Nginx、ALB、CDN)主动切断了空闲连接。Nginx 默认 proxy_read_timeout 是 60 秒,如果后端需要等 90 秒,它会在第 60 秒发 RST 给 Flask,浏览器就收不到响应。
- 检查 Nginx 配置:
proxy_read_timeout 120、proxy_send_timeout 120、keepalive_timeout 120 - AWS ALB 要调高
Idle timeout(默认 60 秒),且必须开启Connection: keep-alive透传 - 浏览器端用
fetch时,不能设signal.timeout,否则 JS 层先超时;推荐用AbortController手动控制,失败后立即重试
如何避免多个长轮询请求堆积导致内存泄漏?
每个未完成的长轮询请求在服务端都维持一个线程(同步)或协程(异步),如果客户端网络断开但没发 FIN 包,连接可能假死滞留。不清理就会累积。
- 同步框架(Flask + Gunicorn):用
gunicorn --worker-class gevent --worker-connections 1000,配合gevent.monkey.patch_all() - 异步框架(FastAPI + Uvicorn):用
async def+await asyncio.wait_for(queue.get(), timeout=30),超时自动释放协程栈 - 所有场景下,都要给队列消费加
try/except,并在finally里做清理(比如从 client registry 中移除 dead socket)
Django 中实现长轮询要注意什么?
Django 的同步视图天然不适合长轮询,runserver 会卡死,mod_wsgi 默认也不支持长连接。强行用会触发 ConnectionAbortedError 或 BrokenPipeError。
立即学习“Python免费学习笔记(深入)”;
- 不要用
HttpResponse直接写 body;改用StreamingHttpResponse,但注意它仍基于同步流,无法解决阻塞问题 - 真正可行的是:用 Django Channels +
AsyncWebsocketConsumer替代 HTTP 长轮询,或者把长轮询逻辑拆到独立的 FastAPI 子服务中,用 Redis Pub/Sub 通信 - 如果必须用原生 Django 视图,至少加上
@csrf_exempt和response['Content-Type'] = 'application/json',否则某些中间件会提前终止响应
长轮询真正的难点不在“怎么返回”,而在于连接生命周期管理——谁来判断客户端是否还活着,超时后状态要不要回滚,重连时数据会不会重复推送。这些细节不处理,上线后第一波流量就会暴露。


















