当前位置: 首页 > web >正文

流式输出阻塞原因及解决办法

流式输出不懂可看这篇文章:流式输出:概念、技巧与常见问题

正常情况,如下代码所示:

    async def event_generator():# 先输出数字1yield "data: 1\n\n"# 然后每隔2秒输出数字2,共输出10次for i in range(10):await asyncio.sleep(2)  # 等待2秒yield "data: 2\n\n"return StreamingResponse(event_generator(),media_type="text/event-stream",)

一、网络缓存

在FastAPI中实现Server-Sent Events (SSE)流式响应时,经常遇到响应数据不是实时发送给客户端,而是累积到一定程度后一次性发送的问题。这主要由以下几个原因造成:

  • 网络层缓冲机制:网络协议栈为了提高传输效率,会将小的数据包进行缓冲合并,这种现象称为Nagle算法或TCP延迟确认。
  • 应用层缓冲:
    Web服务器(如uvicorn)和ASGI应用本身可能对响应内容进行缓冲
    Python的异步框架在处理异步生成器时,可能会将多个yield值缓存起来批量处理
  • 事件循环调度:
    在同一个异步函数中连续调用yield时,事件循环可能不会立即切换到发送数据的协程
    需要显式地让出控制权,使事件循环有机会处理数据发送

解决方法:

  • 事件循环控制权让出:
    await asyncio.sleep(0)会让当前协程暂停执行,并将控制权交还给事件循环
    事件循环会处理其他待处理的任务,包括将已生成的数据发送给客户端

  • 打破缓冲机制:
    通过在每次yield后添加await asyncio.sleep(0),强制中断当前协程的连续执行
    这给底层传输机制一个机会来刷新缓冲区并发送数据

    async def event_generator():# 先输出数字1yield "data: 1\n\n"# 如果是下面这种就会产生阻塞,需要使用 await asyncio.sleep(0)for event in coze.chat.stream(bot_id=bot_id,user_id=user_id,additional_messages=user_messages,):if event.event == ChatEventType.CONVERSATION_MESSAGE_DELTA:yield f"data: {event.message.content}\n\n"# 强制刷新缓冲区,确保数据立即发送await asyncio.sleep(0)return StreamingResponse(event_generator(),media_type="text/event-stream",)

二、Nginx 缓存

Nginx 作为反向代理时,流式输出出现问题是很常见的问题。Nginx 默认会缓冲后端的响应,这会导致流式传输无法正常工作,主要原因包括:

  • Nginx默认启用缓冲,会等待后端响应完成后再转发给客户端
  • HTTP/1.0的连接行为可能中断流式传输
  • 超时设置过短导致连接被提前关闭

第一步:在返回方法处,添加 headers 参数,如下

return StreamingResponse(generate_stream(agent_id, BOT_ID, file_id, content, background_tasks),media_type="text/event-stream",headers={"Cache-Control": "no-cache","Connection": "keep-alive","X-Accel-Buffering": "no"  # 禁用Nginx缓冲})

第二步:如果第一步未解决,则修改Nginx配置文件,添加关键配置下面几行

    location /api/ {proxy_pass http://127.0.0.1:8051/;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_buffering off;proxy_cache off;proxy_read_timeout 86400s;proxy_send_timeout 86400s;}
http://www.xdnf.cn/news/16906.html

相关文章:

  • Pydantic模块学习
  • vivado扫盲:dcp(腾讯元宝)
  • QT6 源,十章绘图(2)画刷 QBrush:刷子只涉及填充颜色,线型,填充图片,以及变换矩阵这几个属性,附源代码带注释。
  • 从零到一:Linux内核MMU启动与虚拟内存体系建立全流程详解
  • gitlab+jenkins的ci/cd部署
  • win11 命令禁用客户体验改善计划
  • 区块链概述
  • 云计算k8s集群部署配置问题总结
  • ARM Cortex-M 处理器的应用
  • Hive SQL (HQL) 编辑指南
  • vscode cursor配置php的debug,docker里面debug
  • 20250801在Ubuntu24.04.2LTS下编译firefly_itx_3588j的Android12时解决boot.img过大的问题
  • django的数据库原生操作sql
  • PHP在现代Web开发中的应用与优势分析
  • ACS-电机控制Buffer-任意路径规划(PVSPLINE绘制圆形)
  • OCC任务新SOTA!华科提出SDGOCC:语义深度双引导的3D占用预测框架(CVPR 2025)
  • Shader开发(六)什么是着色器
  • SQL数据库连接Python实战:疫情数据指挥中心搭建指南
  • STM32 使用 RTC 实现实时时钟功能
  • 【BFS】P7555 [USACO21OPEN] Maze Tac Toe S|普及+
  • Java Map和Set
  • Redis 初识Redis
  • 校园交友|基于SprinBoot+vue的校园交友网站(源码+数据库+文档)
  • 逻辑回归在银行贷款审批中的应用:参数选择与实践
  • 《人形机器人的觉醒:技术革命与碳基未来》——类人关节设计:柔性驱动革命之液压人工肌肉
  • 【C#学习Day14笔记】泛型、集合(数组列表Arraylist、列表list)与字典
  • 利用 AI 在 iPhone 上实现 App 文本情绪价值评估(上)
  • 数据结构学习基础和从包装类缓存到泛型擦除的避坑指南
  • 九联UNT403HS_海思MV320处理器_安卓9-优盘强刷刷机包
  • 代码随想录算法训练营第三十八天