当前位置:   article > 正文

FastAPI Web框架教程 第12章 异步async-await_fastapi async

fastapi async

12-1 fastapi是异步Web框架

从本教程开篇,我们就说FastAPI这个web框架是异步框架,那它到底是如何体现异步的呢?

想要学习使如何使用FastAPI的异步功能,那就必须要先了解什么是异步,什么是asyncio、async/await

【基础补充】

关于异步编程、协程实行的异步编程的基础知识

【重要结论】

本质上,实现异步的方式有三种:多进程、多线程和协程,FastAPI实现异步使用了多线程(线程池)和协程的方式

  • 当我们写普通形式的代码时:即使用 def 定义路径函数,FastAPI内部帮我们使用多线程(线程池)实现异步并发
  • 当我们写async形式的代码时:即使用 async def定义路径函数,FastAPI内部使用协程的方式实现异步并发。
  • 在一个项目中,我们可以同时普通函数定义的路径函数(api),和async def 形式定义的路径函数(api)
  • 但是要记得,在async def 形式定义的函数内,不能使用同步的代码,否则接口的响应速度极慢。

12-2 比较同步和异步代码

在FastAPI中可以使用普通函数定义的接口,也可以使用async def 实行定义的接口。但是使用是需要注意,否则会导致程序极慢。

示例1:普通函数形式定义的接口,会按照多线程(线程池)的方式异步执行

  • 比如这个接口,使用time.sleep(5)模拟耗时5s
  • 当两个客户端同时访问该接口时,服务端就会收到两个请求,因为FastAPI内部使用多线程的方式来处理,一个请求会被一个线程来处理,两个线程几乎同时执行。于是5秒后,两个请求都得到了响应。
import time
from fastapi import FastAPI

app = FastAPI()


@app.get("/")
def index():
    time.sleep(5)
    return "index"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

示例2:async def 形式的定义的接口,使用单线程协程的形式异步执行

  • 因为使用了协程的方式,当有两个客户端发请求时,单线程内代码块级别的切换,最终5秒后两个客户端都会得到响应。

  • 注意:协程时不能使用同步阻塞的time模块,需要使用asyncio.sleep()。又因为它是协程对象,所以需要使用await才能被执行。

  • 另外,await必须使用在async定义的函数内,否则报错。

  • 同时注意,在async def 内部不能使用同步模块,否则就会编程单线程同步执行的方式。

import asyncio
from fastapi import FastAPI

app = FastAPI()


@app.get("/")
async def index():
    await asyncio.sleep(5)
    return "index"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

示例3:在协程函数内错误使用同步模块

  • 因为使用async def定义的函数,所以FadtAPI内部使用单线程的协程方式运行代码,所以当两个客户端发请求时,服务端只有一个线程处理两个请求。
  • 但因为是同步阻塞5秒,所以只能等第一个请求5秒后处理完,才能开始执行第二个请求。所以第二个请求等待了10秒才能得到响应。
import time
from fastapi import FastAPI

app = FastAPI()


@app.get("/")
async def index():
    time.sleep(5)		# 不能在async def 函数内使用同步阻塞模块。
    return "index"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

【注意】

  • 演示上述代码时,不要在一个浏览器上开两个tab页,可能无法演示出效果。这是因为有些浏览器有设置,一个host之后一个连接,所以打开的两个tab也通用一个和服务端通信的连接,此时的效果就是第一个请求得到响应后才开始第二个响应。
  • 你可以使用两个不同的浏览器演示示例;或者开两个cmd窗口,使用 curl命令来发请求。

在这里插入图片描述

12-3 同步异步如何选择

FastAPI非常灵活,支持你写普通的函数,也支持你写async def 形式的函数,那到底该如何选择?

下面有几个原则,可以帮助大家做选择:

  • 你需要使用一个普通的,内部有IO等待的第三方库,此时使用 def
@app.get('/')
def results():
    results = some_library()
    return results
  • 1
  • 2
  • 3
  • 4
  • 你需要使用的一个第三方库,需要使用 await调用时,此时使用 async def</
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/一键难忘520/article/detail/912059
推荐阅读
相关标签
  

闽ICP备14008679号