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

FastAPI 流式响应中,如何优雅处理客户端断连后的数据库操作?

问题出现过程

1. 客户端发起流式对话请求

我们从一个典型的流式对话接口开始。我们使用依赖注入来获取一个 SQLAlchemy 的 AsyncSession,在对话开始时创建消息,在对话结束后更新 AI 的回答。

流式对话原始代码(伪代码)

2. 客户端取消对话(主动断开)

当用户取消发送时,会抛出这个异常

pymysql.err.InterfaceError:

原因:当客户端断开时 ,FastAPI 会立即把它的 session连接回收掉,底层的那个物理连接被标记为 Cancelled,然后执行finally的时候,再往下传原来session连接就不对了,save_conversation函数就会抛pymysql.err.InterfaceError。

问题解决尝试

尝试一:在 save_conversation 函数中创建新连接

一个自然的想法是:既然旧的 session 不能用了,那就在保存的时候检查一下,如果不可用就创建一个新的。

代码更新

结果:失败! 没想到,即使创建了新的 session,依然抛出了 pymysql.err.InterfaceError。

原因分析:之所以还会抛错误,原因是这个新会话 依然在使用已经被取消的连接池资源,因为 FastAPI/Starlette 在主请求取消时,会把整个 AsyncSessionLocal() 对象的连接都标记为 “cancelled”。即便你重新 async with AsyncSessionLocal(),底层复用的还是同一个数据库连接池里的连接,而那个连接刚被 cancel。

重新创建个数据库引擎 是肯定可以的,但是只是对话后更新,这么搞完全没必要。

或者创建个独立线程,在新线程中去创建新连接,应该是可以的,个人还是感觉比较重,浪费资源。

尝试二:创建个协程去执行save_conversation

代码更新

疑惑点:asyncio.create_task 启动的协程仍然跑在同一个线程和进程里,也会复用那个全局的连接池,理论上确实还有可能拿到刚才那个被 cancel 的连接啊?

主要在于操作的时序和上下文隔离:

先清理,后执行

当原始请求被取消后,FastAPI 会立即开始清理与该请求相关的资源(包括回收它持有的数据库连接)。这个清理动作在 finally 块中调用 create_task 之前就已经触发了。我们派生出的后台任务是在这个清理逻辑之后才启动的。

上下文隔离

这个后台协程已经完全不挂在 HTTP 请求的上下文上了。客户端断开与否,都影响不了它的独立运行。只要连接池中还有任意一个好连接,它就能完成写入。

高成功率

因为顺序已经变成了:先断开、先清理 → 再新建、再执行,所以新任务向连接池请求时,拿到那个“坏掉”连接的概率已经大大降低。连接池会优先分配一个健康的、空闲的连接。

即使在极端情况下又拿到了旧连接,它也很有可能在 session.begin() 阶段就失败,我们还可以在后台任务的 try...except 块里加入重试逻辑(比如 await asyncio.sleep(0.1) 后重试),进一步提高健壮性。

大量测试后,发现真没问题😁。

结论

对于需要确保最终操作(如数据写入)一定执行的流式 API,asyncio.create_task 提供了一种轻量级且非常有效的解决方案。它避免了引入像 Celery 这样复杂的任务队列,同时优雅地解决了因客户端断连导致资源状态污染的问题。

通过将关键的收尾工作与不稳定的 HTTP 请求生命周期解耦,我们能构建出更加健壮和可靠的 FastAPI 应用。"

http://www.cnnetsun.cn/news/114734.html

相关文章:

  • MiniCPM-V 4.5
  • Flutter工程化与协作实践指南
  • Excel技巧:提取身份证号码中的出生年月日
  • 软工毕业设计创新的开题分享
  • Oracle数据库物理备份与恢复实战指南
  • 告别“养死”魔咒!AI+知识库+物联网,打造零失败智能种植系统(附架构图+实操指南)
  • 安卓基础之《(4)—Activity组件(2)》
  • 打破数据堵点:6 大主流CRM厂商全链路数据流转能力横评与选型指南
  • 小程序毕设项目:基于springboot+微信小程序的校园活动管理系统设计与实现(源码+文档,讲解、 调试运行,定制等)
  • 小程序毕设项目:基于springboot+微信小程序的DIY电脑推荐与交流平台(源码+文档,讲解、 调试运行,定制等)
  • 小程序毕设项目:基于springboot+微信小程序的在线复习小程序(源码+文档,讲解、 调试运行,定制等)
  • 安徽做SCARA机器人的公司有哪些?
  • 【JavaWeb】MVC模式_理论简介
  • 【JavaWeb】日程管理01——登录页及数据校验功能
  • springboot中File默认路径
  • 【2025年AI 编程时代的热点】
  • 【C++ 笔记】从 C 到 C++:核心过渡 (中)
  • SQL约束解析
  • 地铁调研12-17
  • 现代软件测试工具全景对比与选型指南
  • 基于 Apache POI 的体检报告 Word 生成实战文档
  • org.jetbrains.annotations的@Nullable 学习
  • 计算机毕业设计springboot计算机硬件自配系统 基于Spring Boot的计算机硬件配置管理系统设计与实现 Spring Boot架构下的计算机硬件自选系统开发
  • 【信创】中间件对比
  • 傅里叶变换小波变换
  • 智能桑拿房首选:水管家集成系统如何提升体验?
  • 最简单的LangChain和RAG
  • 空压机监控运维管理系统方案
  • 实习面试题-Rust 面试题
  • 视频字幕精确生成方法 用到字幕api开发文档