FastAPI性能对比:同步vs异步

大家好,FastAPI已成为构建Python API的最流行框架之一,因其速度和易用性而广受欢迎。但在构建高性能应用程序时,使用同步(sync)还是异步(async)代码执行是很重要的问题。本文将通过现实世界的性能测试,对同步和异步的FastAPI实现进行基准测试,并深入分析相关数据,以帮助大家决定何时使用这两种方法。

1.同步与异步在FastAPI中的区别

  • 同步代码(sync):在同步执行中,任务一个接一个地处理。每个请求都需要等待前一个请求完成,这在用户数量较多或存在慢I/O操作(如数据库查询或文件上传)时,可能会导致瓶颈。

  • 异步代码(async):异步执行支持多个请求并发处理。应用程序无需等待I/O操作(如数据库调用)完成,而是可以继续处理其他请求,从而在高并发环境中更有效率。

2.设置:在FastAPI中基准测试同步与异步

为了比较同步和异步实现,在这里创建了两个版本的FastAPI应用程序。

同步版本:使用传统的阻塞数据库查询,采用psycopg2

异步版本:使用非阻塞的异步查询,采用asyncpg

这两个版本都执行一个简单的任务:从PostgreSQL数据库查询用户。数据库中包含极少的数据,以便隔离同步/异步机制的影响。

技术栈:

  • 使用FastAPI作为API框架。

  • 使用SQLAlchemy作为ORM。

  • 使用psycopg2或psycopg2-binary(同步)和asyncpg(异步)进行数据库连接。

  • 使用PostgreSQL作为数据库。

为了测试性能,使用**Apache Benchmark(ab)**模拟了1000个请求,具有100个并发连接。

2.1 同步版本代码

在同步版本中,在这里使用psycopg2驱动与SQLAlchemy,后者可执行阻塞查询。表格是使用同步的SQLAlchemy引擎创建的。

同步:main.py

from fastapi import FastAPI, Depends, HTTPException
from sqlalchemy.orm import Session
from .database import get_db, Userapp = FastAPI()@app.get("/users/{user_id}")
def get_user(user_id: int, db: Session = Depends(get_db)):# 同步和阻塞user = db.query(User).filter(User.c.id == user_id).first()if not user:raise HTTPException(status_code=404, detail="User not found")return {"id": user.id, "name": user.name, "email": user.email}

同步:database.py

from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String
from sqlalchemy.orm import sessionmakerDATABASE_URL = "postgresql://user:password@localhost/db_name"# 创建同步的SQLAlchemy引擎
engine = create_engine(DATABASE_URL, echo=True)# 创建用于同步查询的会话生成器
SessionLocal = sessionmaker(bind=engine, autoflush=False, autocommit=False)# 定义元数据
metadata = MetaData()# 定义User表
User = Table("users", metadata,Column("id", Integer, primary_key=True),Column("name", String),Column("email", String),
)# 在数据库中创建表
metadata.create_all(engine)# 获取同步数据库会话的依赖
def get_db():db = SessionLocal()try:yield dbfinally:db.close()

2.2 异步版本代码

在异步版本中,在这里使用asyncpg驱动与SQLAlchemy,进行非阻塞查询。然而,表的创建仍然是同步进行的,因为SQLAlchemy的metadata.create_all()不支持异步。

异步:main.py

from contextlib import asynccontextmanager
from fastapi import FastAPI, Depends, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from .database import get_async_db, User, initialize_database@asynccontextmanager
async def lifespan(app: FastAPI):# 启动:初始化数据库await initialize_database()yieldapp = FastAPI(lifespan=lifespan)@app.get("/users/{user_id}")
async def get_user(user_id: int, db: AsyncSession = Depends(get_async_db)):result = await db.execute(select(User).where(User.c.id == user_id))user = result.fetchone()if not user:raise HTTPException(status_code=404, detail="User not found")return {"id": user.id, "name": user.name, "email": user.email}

异步:database.py

from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy import MetaData, Table, Column, Integer, StringDATABASE_URL = "postgresql+asyncpg://user:password@localhost/db_name"# 用于异步查询的异步引擎
engine = create_async_engine(DATABASE_URL,echo=True,pool_size=10,max_overflow=20,
)# 用于异步查询的异步会话
AsyncSessionLocal = sessionmaker(bind=engine, class_=AsyncSession, expire_on_commit=False
)# 定义元数据
metadata = MetaData()# 定义User表
users = Table("users",metadata,Column("id", Integer, primary_key=True),Column("name", String),Column("email", String),
)# 创建所有表
async def init_db():async with engine.begin() as conn:await conn.run_sync(metadata.create_all)# 获取异步数据库会话的依赖
async def get_async_db():async with AsyncSessionLocal() as session:yield session# 启动:初始化数据库
async def initialize_database():await init_db()

在这个版本中,请求是以异步方式处理的,支持多个请求在等待I/O时并发处理。

3.基准测试命令

同步版本:ab -n 1000 -c 100 http://127.0.0.1:8000/users/1

异步版本:ab -n 1000 -c 100 http://127.0.0.1:8001/users/1

以下是基准测试的性能指标分析:

图片

同步vs异步(Airtable)的基准测试结果如下。

每秒请求数:异步版本每秒可处理50.68个请求,而同步版本每秒只能处理36.89个请求。在相同时间内,异步处理的请求数比同步版本多37%,因此在并发性方面,异步显然胜出。

每个请求的响应时间(平均值):异步版本的平均响应时间低于同步版本27%(1973毫秒vs2710毫秒),这表明在高负载情况下,异步处理请求的效率更高。

最长请求时间:两个版本的最长请求时间相似(约4000毫秒),但异步版本的表现更稳定,这体现在响应时间的波动较小。

图片

以上是同步和异步版本在不同百分位数下的比较图,包括平均和最长请求时间。

  • 实线表示不同百分位数下的响应时间。

  • 虚线表示同步(2710.648毫秒)和异步(1973.057毫秒)的平均响应时间。

  • 点线突出显示同步(4167毫秒)和异步(3851毫秒)的最长请求时间。

4.FastAPI中同步与异步的选择

使用异步的情况:

  • 应用程序需要处理高流量和大量并发用户。

  • 应用程序是与I/O绑定的,需要进行大量数据库查询或API调用。

  • 需要为大量请求最小化响应时间。

使用同步的情况:

  • 应用程序的并发量较小,或主要执行CPU密集型任务。

  • 希望保持代码库的简单性,避免异步处理的复杂性。

  • 不希望应用程序扩展到同时处理数百或数千个请求。

5.优化异步性能

虽然异步在这些测试中速度更快,但仍有一些方法可以进一步优化。

  • 连接池:使用连接池重用数据库连接,避免为每个请求创建一个新连接。

  • 使用异步库:确保所有I/O绑定的任务(例如文件读/写、外部API调用)都以异步方式处理,以获得最佳性能。

  • 测试更高的并发性:进行更高并发量的负载测试(例如,500+用户),以充分发挥异步的优势。

engine = create_async_engine(DATABASE_URL,pool_size=10,max_overflow=20
)

如果应用程序需要处理大量并发用户,并严重依赖于I/O绑定任务,那么异步FastAPI可以提供更好的性能、可扩展性和响应能力。不过对于更简单的用例,可以选择同步实现。

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

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

相关文章

wx.setNavigationBarColor动态设置导航栏颜色无效(亲测有效)

wx.setNavigationBarColor动态设置导航栏颜色无效(亲测有效) 问题描述问题分析问题解决注意 问题描述 wx.setNavigationBarColor({frontColor: #E6E6E6,backgroundColor: #E6E6E6 })上面的代码设置后导航栏颜色没有变化,查看了app.json 以及…

Blender进阶:贴图与UV

9 UV 9.1 贴图与UV UV,指定每个面顶点在贴图上的坐标 演示: 1、添加物体 2、添加贴图,即图片纹理节点 3、进入UV Edit工作区 4、右边,选择一个面 5、左边,选择一个面,移动这个面 9.2 电子表格 电子…

利用LangChain与LLM打造个性化私有文档搜索系统

我们知道LLM(大语言模型)的底模是基于已经过期的公开数据训练出来的,对于新的知识或者私有化的数据LLM一般无法作答,此时LLM会出现“幻觉”。针对“幻觉”问题,一般的解决方案是采用RAG做检索增强。 但是我们不可能把…

PostgreSQL-06-入门篇-集合运算

文章目录 1. UNION 组合多个查询的结果集简介带有 ORDER BY 子句的 UNION设置样例表PostgreSQL UNION 示例1) 简单的 PostgreSQL UNION 示例2) PostgreSQL UNION ALL 示例3) 带 ORDER BY 子句 UNION ALL 示例 2. INTERSECT 取交集简介带 ORDER BY 子句的 INTERSECT 操作Postgre…

云计算作业二Spark:问题解决备忘

安装spark 教程源地址:https://blog.csdn.net/weixin_52564218/article/details/141090528 镜像下载 教程给的官网下载地址很慢,https://archive.apache.org/dist/spark/spark-3.1.1/ 这里的镜像快很多: 清华软件源:https://mi…

(51)MATLAB迫零均衡器系统建模与性能仿真

文章目录 前言一、迫零均衡器性能仿真说明二、迫零均衡器系统建模与性能仿真代码1.仿真代码2.代码说明3.迫零均衡器zf_equalizer的MATLAB源码 三、仿真结果1.信道的冲击响应2.频率响应3.迫零均衡器的输入和输出 前言 使用MATLAB对迫零均衡器系统进行建模仿真,完整的…

【C#】编写计算机选课程序

文章目录 一、引言二、程序概述三、程序设计四、 界面设计五、代码实现六、为每一个选项添加事件七、事件处理八、完成展示 一、引言 在这篇文章中,我将介绍如何开发一个简单的计算机选课程序。这个程序将允许学生根据自己的需求选择不同等级的课程,并即…

【AIGC】AI工作流workflow实践:构建日报

workflow实践 引言实现步骤分析实践创建 dify workflow 应用创建工作流内部节点1、设置输入字段2、创建两个LLM节点3、设置结束节点 运行工作流 结语 引言 工作流 workflow 是现在 LLM 很重要的一个概念,因为对于一个模型来说,非常复杂的问题很难一次性…

无人机飞手考证热,装调检修技术详解

随着无人机技术的飞速发展和广泛应用,无人机飞手考证热正在持续升温。无人机飞手不仅需要掌握飞行技能,还需要具备装调检修技术,以确保无人机的安全、稳定和高效运行。以下是对无人机飞手考证及装调检修技术的详细解析: 一、无人机…

034_Structural_Transient_In_Matlab结构动力学问题求解

结构动态问题 问题描述 我们试着给前面已经做过的问题上加一点有趣的东西。 结构静力学求解 当时求解这个问题,在最外面的竖直切面加载了一个静态的固定的力。下面我们试试看在上方的表面增加一个脉冲压力载荷。 采用统一的有限元框架,定义问题&…

江协科技STM32学习- P23 DMA 直接存储器存取

🚀write in front🚀 🔎大家好,我是黄桃罐头,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流 🎁欢迎各位→点赞👍 收藏⭐️ 留言📝​…

「Math」高等数学知识点大纲(占位待处理)

✨博客主页何曾参静谧的博客📌文章专栏「C/C」C/C程序设计📚全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasoli…

linux-UART

参考博客 https://blog.csdn.net/m0_38106923/article/details/126024970?sharetypeblog&shareId126024970&sharereferAPP&sharesourceweixin_40933496&sharefromlink 1.串口 UART的全称是Universal Asynchronous Receiver and Transmitter,即异步…

mac如何下载 测试旧版chrome兼容问题

mac安装低版本的chrome 下载地址: Download older versions of Google Chrome for Windows, Linux and Mac 下载需要模拟的浏览器版本 记住版本号 1、下载后安装 安装时提醒 保留两者 2、可能会提醒无法验证 3、设置允许 就可以打开 4、打开后发现还是新版本的浏…

【软服之家-注册安全分析报告-无验证方式导致安全隐患】

前言 由于网站注册入口容易被黑客攻击,存在如下安全问题: 1. 暴力破解密码,造成用户信息泄露 2. 短信盗刷的安全问题,影响业务及导致用户投诉 3. 带来经济损失,尤其是后付费客户,风险巨大,造…

数据治理,数据提取,大数据中心建设,大数据治理总体解决方案书(word,ppt原件)

1. 数据管理的现状 2. 数据治理的概述 1.1数据治理概念 2.2数据治理目标 3. 数据治理体系 4. 数据治理核心领域 1.1 数据模型 1.2 数据生命周期 (1)数据生成及传输 (2)数据存储 (3)数据处理和应用…

C++设计模式结构型模式———桥接模式

文章目录 一、引言二、桥接模式三、总结 一、引言 桥接(Bridge)模式也叫桥梁模式,简称桥模式,是一种结构型模式。该模式所解决的问题非常简单,即根据单一职责原则,在一个类中,不要做太多事&…

Rust 力扣 - 48. 旋转图像

文章目录 题目描述题解思路题解代码题目链接 题目描述 题解思路 我们可以将原矩阵进行水平翻转&#xff0c;然后在沿主对角线进行翻转&#xff0c;就能完成原矩阵沿顺时针方向旋转90o的变换 题解代码 impl Solution {pub fn rotate(matrix: &mut Vec<Vec<i32>&…

SQL 基础语法(一)

文章目录 1. SQL 分类2. 数据库操作3. 数据表操作4. 增删改操作5. 查询操作6. 用户管理7. 权限控制 1. SQL 分类 2. 数据库操作 #创建数据库 create database if not exists test;#查询所有数据库 show databases;#查询当前数据库 select database();#删除数据库 drop databas…

高效水电管理:Spring Boot在大学城的应用

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所&#xff0c;二十一世纪是信息的时代&#xff0c;所以信息的管理显得特别重要。因此&#xff0c;使用计算机来管理大学城水电管理系统的相关信息成为必然。开…