Django3.2.5使用SSE连接建立慢、响应吞吐量低问题咨询
问题原因分析
你遇到的连接建立慢、批量发送数据、周期性停顿的核心原因是各级服务的输出缓冲机制,以及未配置SSE要求的专用响应头,和StreamingHttpResponse本身的逻辑无关。
具体原因拆解
- 连接初始化耗时32秒的原因
绝大多数WSGI服务器(包括Django自带的runserver、Gunicorn、uWSGI)、反向代理(Nginx等)默认都开启了输出缓冲,通常默认缓冲区大小为4KB。只有当返回的内容累计达到缓冲区阈值时,才会将响应头+缓存的内容一次性发送给客户端。你的代码每次yield的SSE消息仅约24字节,每200ms发送1条,攒够4KB刚好需要约32秒,此时浏览器才会收到响应头,触发EventSource的onopen事件,所以你感知到连接建立耗时很长。 - 每32秒仅发送167条、周期性停顿的原因
167条消息的总大小恰好接近4KB的缓冲区阈值,所以每攒够167条才会批量flush一次给前端;第二批发送完成后的32秒停顿是因为服务器默认的单请求超时限制(通常为30~35秒),超时后服务端主动断开连接,EventSource触发自动重连逻辑,重连时又会再次经历32秒的缓冲等待,才会收到新的响应。
解决方案
你需要从代码配置、服务启动参数两个层面禁用所有缓冲,同时调整超时设置:
1. 代码层面补全SSE专用响应头
修改你的视图代码,明确告诉所有中间层不要缓存SSE响应:
import sys from datetime import datetime from time import sleep from django.http import StreamingHttpResponse def sse_movies(request): def event_stream(): while True: sleep(.2) yield f"data: {datetime.time(datetime.now())}\n\n" # 可选:手动flush Python层的标准输出缓冲 sys.stdout.flush() response = StreamingHttpResponse(event_stream(), content_type='text/event-stream') # 禁用所有层级的缓存 response['Cache-Control'] = 'no-cache' response['Connection'] = 'keep-alive' # 禁用Nginx等反向代理的缓冲 response['X-Accel-Buffering'] = 'no' return response
2. 调整服务启动参数禁用缓冲
- 如果用Django自带的runserver做开发测试,启动时增加环境变量禁用Python缓冲:
PYTHONUNBUFFERED=1 python manage.py runserver - 如果用Gunicorn部署,启动时添加禁用缓冲、调整超时的参数:
gunicorn --worker-class gevent --timeout 0 --buffer-size 0 your_project.wsgi - 如果用uWSGI部署,添加配置:
post-buffering = 0 socket-timeout = 86400
3. 反向代理配置(如果有Nginx)
如果前面搭了Nginx反向代理,需要在站点配置里增加以下参数,避免代理层缓冲和超时断开:
location /test/sse/movies/ { proxy_pass http://your_upstream; proxy_set_header Connection ''; proxy_http_version 1.1; chunked_transfer_encoding off; proxy_buffering off; proxy_cache off; proxy_read_timeout 86400s; }
按照以上配置调整后,SSE消息会实时发送给前端,不会再出现批量发送、连接建立慢的问题。
内容的提问来源于stack exchange,提问作者Ahmed ELMawrdy
相关产品推荐
相关产品推荐

