首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >关于FastAPI异步并发的技术背景和细节

关于FastAPI异步并发的技术背景和细节

作者头像
dongfanger
发布2022-11-28 20:56:15
9990
发布2022-11-28 20:56:15
举报
文章被收录于专栏:dongfangerdongfanger

FastAPI的路径操作函数,可以使用async def定义:

from typing import Union

from fastapi import FastAPI

app = FastAPI()


@app.get("/")
async def read_root():
    return {"Hello": "World"}


@app.get("/items/{item_id}")
async def read_item(item_id: int, q: Union[str, None] = None):
    return {"item_id": item_id, "q": q}

这算得上是FastAPI的典型特征之一。

关于这个框架设计,有哪些技术背景和细节呢?

技术背景

在Python语法里面,如果你想异步请求三方库,需要使用await:

results = await some_library()

使用了await就必须在def前面加上async:

@app.get('/')
async def read_results():
    results = await some_library()
    return results

这是Python语法规定。

FastAPI并不要求所有的路径操作函数,都必须定义为async,假如你要实时访问某些三方库,可以简单的使用def就行,不用加上await:

@app.get('/')
def results():
    results = some_library()
    return results

但是无论你是否使用async,FastAPI都将异步工作,以达到"Fast"的运行速度。

看完文章就明白这句话的意思了。

技术细节

Python新版本已经原生支持异步代码了。所谓异步代码,指的是编程语言,会告诉计算机程序,在某个时刻停下来,等待其他任务完成后,再继续运行。在等待期间,计算机程序可以去干点别的事情,而不用一直卡在那里。这些“其他任务”,通常指的是耗时较长的IO操作,比如:

  • 客户端通过网络发送数据;
  • 服务端通过网络发送数据;
  • 程序从磁盘读取文件内容;
  • 程序将文件内容写入磁盘;
  • 远程API操作;
  • 数据库操作;
  • 数据库查询返回结果;

这些操作主要阻塞在IO等待,所以又叫做IO密集型。

并发和并行

异步有时候也叫做并发。并发(Concurrency)和并行(parallelism)是不同的概念,并发是指一个处理器同时处理多个任务,并行是指多个处理器同时处理多个不同的任务,并发是逻辑上的同时发生,并行是物理上的同时发生。

并发

餐厅有1个服务员和1个厨子。

你带女朋友到餐厅排队点汉堡:

你们给服务员说来2个汉堡:

服务员给厨师说做2个汉堡:

然后给了你们一个排号:

你们开心的等,因为有排号,不需要担心别人会抢走:

叫号了:

取了汉堡高高兴兴的吃:

并行

餐厅有5个服务员兼厨子。

你们看哪个窗口有空位:

到餐台点2个汉堡:

服务员自己跑到厨房做汉堡:

你们只能站在原地等,如果走开,可能会被其他人拿走:

汉堡做好了:

你的女朋友不开心:

从这个买汉堡的漫画中,可以看到并行比并发会做更多无意义的等待,并行需要5个人(5个服务员兼厨子),并发只需要2个人(1个服务员1个厨子)。这就是为什么很多Web框架要设计成异步并发了,因为很多客户端会发请求给服务端,然后服务端响应给客户端,如果有太多无用的等待,那么整个应用将慢得无法使用。而且硬件资源有限,并发也能更高效利用资源,节约成本。

并发一定就比并行好吗?也不是,只有在出现很多等待时,并发才比并行好。比如你们要打扫房间,一间一间的打扫,没有等待,那么并发和并行就没有区别,如果你再叫3个朋友一起打扫,并行就能更快打扫完。这种执行时间完全取决于任务本身而不是等待的情况,又叫做CPU密集型。计算机里的CPU密集型操作通常需要更复杂的数据计算,比如:

  • 音频或图片处理;
  • 计算机视觉;
  • 机器学习;
  • 深度学习;

FastAPI既支持异步并发,也支持多线程并行。

async和await

异步并发使用async和await来实现。

async定义函数:

async def get_burgers(number: int):
    # Do some asynchronous stuff to create the burgers
    return burgers

await调用函数:

@app.get('/burgers')
async def read_burgers():
    burgers = await get_burgers(2)
    return burgers

细节中的细节

FastAPI会对路径操作函数(path operation function)和依赖(dependencies)进行特殊处理。这个特殊处理是:如果你把函数定义为def而不是async def,那么FastAPI会把它放到单独的线程池中,异步执行,这就是FastAPI精彩的地方。就像官方所说,如果你不清楚你函数里面的调用是不是异步(能不能用await),那么就把它定义为普通函数,FastAPI会采用多线程的方式处理。乱用async,在async里面有同步调用,则会变成串行,Fast秒变Slow。

而对于其他函数,FastAPI则不会管,def就是同步调用,立马返回结果。

现在回过头来看前面的那句话:但是无论你是否使用async,FastAPI都将异步工作,以达到"Fast"的运行速度。应该更加明白了。

参考资料: Concurrency and async / await - FastAPI https://fastapi.tiangolo.com/async/ 很火的Fastapi框架,用async函数真的比普通函数快吗?https://blog.csdn.net/yyw794/article/details/108859240

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-11-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 技术背景
  • 技术细节
    • 并发和并行
      • async和await
      • 细节中的细节
      相关产品与服务
      图片处理
      图片处理(Image Processing,IP)是由腾讯云数据万象提供的丰富的图片处理服务,广泛应用于腾讯内部各产品。支持对腾讯云对象存储 COS 或第三方源的图片进行处理,提供基础处理能力(图片裁剪、转格式、缩放、打水印等)、图片瘦身能力(Guetzli 压缩、AVIF 转码压缩)、盲水印版权保护能力,同时支持先进的图像 AI 功能(图像增强、图像标签、图像评分、图像修复、商品抠图等),满足多种业务场景下的图片处理需求。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档