【最后203篇系列】028 FastAPI的后台任务处理

说明

今天偶然在别的文章里看到这个功能,突然觉得正好。

CeleryWorker已经搭好了,但是我一直想在用户请求时进行额外的处理会比较影响处理时间,用这个正好可以搭配上。
在这里插入图片描述
在这里插入图片描述
我设想的一个场景:

  • 1 用户发起请求
  • 2 接口中进行关键信息的日志记录 logger.info这种,直接记录在文本文件里
  • 3 影响请求后在后台进行相关操作:在redis中计数,将数据转发kafka等

这样既不会影响请求时间,又可以把需要做的操作,例如在内存中记录,修改状态;采样数据发送做完。

一个比较笨(现在有在用)的方法是在处理时将数据采样发送到kafka,然后担心kafka服务出问题,又做了try…except。当然,最坏的情况也还好,因为调用大模型通常都是数秒。

当然,在接口中logging和redis这样的操作倒是没关系,因为时间足够短。某种程度上来说,logging+ logstash可能是更好的方案,redis都还有可能挂。

还有一个相对好一点的方法(准备好了还没有启用)。使用WCelery发送任务(甚至可以是复杂任务),并且可以再封装一层异步(async httpx),这样也只是多花一个请求时间。

当然这些都不如直接用FastAPI自带的BackgroundTasks方法,这种服务启动嵌入的方法应该更可靠。(其实在flask时代,就有before和after request装饰器)

以下是一个实验代码(主要 by deepseek)

server.py

from fastapi import FastAPI, BackgroundTasks, HTTPException
import time
from typing import Optional
import loggingapp = FastAPI()# 配置日志
logging.basicConfig(filename='app.log', level=logging.INFO)# def write_log(message: str):
#     """记录日志到文件(模拟耗时操作)"""
#     time.sleep(2)  # 模拟耗时操作
#     with open("log.txt", mode="a") as f:
#         f.write(f"{time.ctime()}: {message}\n")
#     logging.info(f"日志已记录: {message}")import aiofiles  # 需要先安装: pip3 install aiofiles
import asyncioasync def write_log(message: str):"""真正的异步日志写入"""await asyncio.sleep(2)  # 正确使用awaitasync with aiofiles.open("log.txt", mode="a") as f:await f.write(f"{time.ctime()}: {message}\n")logging.info(f"日志已记录: {message}")  # logging默认是同步的
def send_email(to: str, subject: str, body: Optional[str] = None):"""模拟发送邮件(带错误处理)"""try:time.sleep(3)  # 模拟网络延迟with open("email_logs.txt", "a") as f:content = f"""Time: {time.ctime()}To: {to}Subject: {subject}Body: {body or 'No content'}{'-'*30}"""f.write(content)print(f"邮件已发送给 {to}")except Exception as e:logging.error(f"邮件发送失败: {str(e)}")def cleanup_temp_files():# aa"""模拟清理临时文件"""time.sleep(1)print("临时文件清理完成")from pydantic import BaseModelclass RegisterInput(BaseModel):username: stremail: str@app.post("/register")
async def register_user(user_input:RegisterInput , background_tasks: BackgroundTasks):"""用户注册接口(演示多个后台任务)"""if not user_input.email.endswith("@example.com"):raise HTTPException(400, "仅支持 example.com 域名")# 添加多个后台任务background_tasks.add_task(write_log,f"新用户注册: {user_input.username}, 邮箱: {user_input.email}")background_tasks.add_task(send_email,to=user_input.email,subject="欢迎注册",body=f"尊敬的 {user_input.username},感谢您的注册!")background_tasks.add_task(cleanup_temp_files)return {"message": "注册成功","details": "激活邮件和日志记录正在后台处理"}@app.get("/stats")
async def get_stats(background_tasks: BackgroundTasks):"""获取统计信息(演示快速响应+后台处理)"""background_tasks.add_task(write_log,"用户查看了统计信息")# 立即返回的简单数据return {"active_users": 42,"note": "详细日志正在后台记录"}if __name__ == "__main__":import uvicornuvicorn.run(app, host="0.0.0.0", port=8000)

test.py

resp = httpx.post('http://127.0.0.1:8000/register', json = {'username':'andy', 'email':'andy@example.com'})

对应产生的几个文件,如log.txt

Fri Apr 18 23:27:02 2025: 新用户注册: andy, 邮箱: andy@example.com
Fri Apr 18 23:28:08 2025: 新用户注册: andy, 邮箱: andy@example.com
Fri Apr 18 23:29:52 2025: 新用户注册: andy, 邮箱: andy@example.com
Fri Apr 18 23:30:33 2025: 新用户注册: andy, 邮箱: andy@example.com
Fri Apr 18 23:39:40 2025: 新用户注册: andy001, 邮箱: andy001@example.com

实验成功,感觉还挺好的。

原文有一些错误,说background_tasks只能执行同步任务,事实证明是错误的。某种程度上说,异步的才符合FastAPI的特点。

在这里插入图片描述
另外,如果有些同步操作时间特别短是可以不用异步的。例如redis操作。
在这里插入图片描述
以上对我有用,希望对你也有用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/79479.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

uboot下读取ubifs分区的方法

在uboot 的defconfig中增加以下内容: CONFIG_MTDIDS_DEFAULT"nand0nand0" CONFIG_MTDPARTS_DEFAULT"mtdpartsnand0:1M(boot1),1M(boot2),1M(hwinfo),6M(kernel1),6M(kernel2),56M(rootfs1),56M(rootfs2),-(ubi2)" CONFIG_CMD_UBIy 其中&#x…

图+文+语音一体化:多模态合成数据集构建的实战与方法论

目录 图文语音一体化:多模态合成数据集构建的实战与方法论 一、多模态合成数据的核心价值 二、系统架构概览 三、核心模块与实现建议 ✅ 1. 文→图:图像合成(Text-to-Image) ✅ 2. 图→文:自动描述(I…

linux驱动之poll

驱动中 poll 实现 在用户空间实现事件操作的一个主要实现是调用 select/poll/epoll 函数。那么在驱动中怎么来实现 poll 的底层呢? 其实在内核的 struct file_operations 结构体中有一个 poll 成员,其就是底层实现的接口函数。 驱动中 poll 函数实现原…

第八篇:系统分析师第三遍——3、4章

目录 一、目标二、计划三、完成情况四、意外之喜(最少2点)1.计划内的明确认知和思想的提升标志2.计划外的具体事情提升内容和标志 五、总结 一、目标 通过参加考试,训练学习能力,而非单纯以拿证为目的。 1.在复习过程中,训练快速阅读能力、掌…

C++17 新特性简解

C17 新特性简解 一、核心语言特性 1. 结构化绑定&#xff08;Structured Bindings&#xff09; 用途&#xff1a;解构复合类型&#xff08;如元组、结构体&#xff09;为独立变量 示例&#xff1a; #include <iostream> #include <tuple>int main() {// 解构 st…

PHP使用pandoc把markdown文件转为word

文章目录 首先安装pandocPHP处理 服务器操作系统是Linux&#xff0c;centos 首先安装pandoc yum install -y pandoc安装完成后输入如下代码&#xff0c;检查安装是否成功 pandoc --versionPHP处理 我把markdown内容存到了数据库里&#xff0c;所以要从数据库读取内容。对内容…

【Python学习笔记】Pandas实现Excel质检记录表初审、复核及质检统计

背景&#xff1a; 我有这样一个需要审核的飞书题目表&#xff0c;按日期分成多个sheet&#xff0c;有初审——复核——质检三个环节&#xff0c;这三个环节是不同的同学在作业&#xff0c;并且领到同一个题目的人选是随机的&#xff0c;也就是说&#xff0c;完成一道题的三个人…

守护进程编程、GDB调试以及外网连接树莓派

目录 一、什么是守护进程以及如何创建守护进程1. 什么是守护进程&#xff1f;2. 如何创建守护进程&#xff1f; 二、什么是GDB调试以及如何用GDB命令调试C程序1. 什么是GDB&#xff1f;2. 如何用GDB命令调试C程序&#xff1f; 三、外网访问树莓派 一、什么是守护进程以及如何创…

Logisim数字逻辑实训——计数器设计与应用

4位递增计数器 六进制计数器 十进制计数器 六十进制计数器 二十四进制计数器 计时器

发现“横”字手写有难度,对比两个“横”字

我发现手写体“横”字“好看”程度&#xff0c;难以比得上印刷体&#xff1a; 两个从方正简体启体来的“横”字&#xff1a; 哪个更好看&#xff1f;我是倾向于左边一点。 <div style"transform: rotate(180deg); display: inline-block;"> 左边是我从方正简…

ubuntu 向右拖动窗口后消失了、找不到了

这是目前单显示器的设置&#xff0c;因为实际只有1个显示器&#xff0c;之前的设置如下图所示&#xff0c;有2个显示器&#xff0c;一个主显示器&#xff0c;一个23寸的显示器 ubuntu 22.04 系统 今天在操作窗口时&#xff0c;向右一滑&#xff0c;发现这个窗口再也不显示了、找…

专精特新政策推动,B端UI设计如何赋能中小企业创新发展?

在当前数字化转型浪潮下&#xff0c;专精特新政策为中小企业提供了强大的支持&#xff0c;助力其在细分领域实现专业化、精细化、特色化和创新化发展。B端UI设计作为提升企业数字化产品用户体验和工作效率的重要手段&#xff0c;能够有效赋能中小企业创新发展。本文将探讨专精特…

梯度下降代码

整体流程 数据预处理:标准化->加一列全为1的偏置项 训练:梯度下降,将数学公式转换成代码 预测 模型代码 import numpy as np# 标准化函数&#xff1a;对特征做均值-方差标准化 # 返回标准化后的特征、新数据的均值和标准差&#xff0c;用于后续预测def standard(feats…

RAG 实战|用 StarRocks + DeepSeek 构建智能问答与企业知识库

文章作者&#xff1a; 石强&#xff0c;镜舟科技解决方案架构师 赵恒&#xff0c;StarRocks TSC Member &#x1f449; 加入 StarRocks x AI 技术讨论社区 https://mp.weixin.qq.com/s/61WKxjHiB-pIwdItbRPnPA RAG 和向量索引简介 RAG&#xff08;Retrieval-Augmented Gen…

从零开始学A2A一:A2A 协议的高级应用与优化

A2A 协议的高级应用与优化 学习目标 掌握 A2A 高级功能 理解多用户支持机制掌握长期任务管理方法学习服务性能优化技巧 理解与 MCP 的差异 分析多智能体场景下的优势掌握不同场景的选择策略 第一部分&#xff1a;多用户支持机制 1. 用户隔离架构 #mermaid-svg-Awx5UVYtqOF…

【C++】入门基础【上】

目录 一、C的发展历史二、C学习书籍推荐三、C的第一个程序1、命名空间namespace2、命名空间的使用3、头文件<iostream>是干什么的&#xff1f; 个人主页<—请点击 C专栏<—请点击 一、C的发展历史 C的起源可以追溯到1979年&#xff0c;当时Bjarne Stroustrup(本…

1panel第三方应用商店(本地商店)配置和使用

文章目录 引言资源网站实战操作说明 引言 1Panel 提供了一个应用提交开发环境&#xff0c;开发者可以通过提交应用的方式将自己的应用推送到 1Panel 的应用商店中&#xff0c;供其他用户使用。由此衍生了一种本地应用商店的概念&#xff0c;用户可以自行编写应用配置并上传到自…

Evidential Deep Learning和证据理论教材的区别(主要是概念)

最近终于彻底搞懂了Evidential Deep Learning&#xff0c;之前有很多看不是特别明白的地方&#xff0c;原来是和证据理论教材&#xff08;是的&#xff0c;不只是国内老师写的&#xff0c;和国外的老师写的教材出入也比较大&#xff09;的说法有很多不一样&#xff0c;所以特地…

text-decoration: underline;不生效

必须得纪念一下&#xff0c;在给文本加下划线时&#xff0c;发现在win电脑不生效&#xff0c;部分mac也不生效&#xff0c;只有个别的mac生效了&#xff0c;思考了以下几种方面&#xff1a; 1.兼容性问题&#xff1f; 因为是electron项目&#xff0c;不存在浏览器兼容性问题&…

VUE SSR(服务端渲染)

&#x1f916; 作者简介&#xff1a;水煮白菜王&#xff0c;一位前端劝退师 &#x1f47b; &#x1f440; 文章专栏&#xff1a; 前端专栏 &#xff0c;记录一下平时在博客写作中&#xff0c;总结出的一些开发技巧和知识归纳总结✍。 感谢支持&#x1f495;&#x1f495;&#…