FastAPI Web开发入门、进阶与实战
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

1.3 asyncio协程概念

我们已经知道,不论是多线程还是多进程,在Python中所用的并发模式都是“假象”。操作系统针对进程和线程进行操作的过程中,需要消耗的资源比较多。而早期多数Web框架都是基于多线程模式来进行并发支持的,在这种情况下进行多用户请求并发处理时,需要为每一个请求创建新的线程并进行对应的处理,这就需要消耗更多资源。

因为系统硬件资源始终有限,所以不可能无限量创建线程或进程来处理更多的并发任务。但是人们对并发的需求却越来越大,怎么办?只能另辟蹊径,考虑在单一进程或线程中是否可以同时处理更多的请求,所以一些IO多路复用模型应运而生。

虽然IO多路复用模型可以让任务执行时不再阻塞在某个连接上,而是当任务处理有数据到达时(阻塞结束)才触发回调并响应请求,但是这种机制依赖于“回调”。这种回调机制使用起来非常复杂,且容易出现链路式回调,编码实现也不够直观,所以后来这种链路式回调机制就慢慢被新的协程机制所替代。

相对于线程来说,协程不存在于操作系统中,它只是一种程序级别上的IO调度。读者可以将它理解为对现有线程进行的一次分片任务处理,线程可以在代码块之间来回切换执行,而非逐行执行,因此能够支持更快的上下文切换,减少线程的创建开销和切换开销,从而大大提高了系统性能。

asyncio是Python官方提供的用于构建协程的并发应用库,是FastAPI实现异步特性的重要组成部分。基于asyncio,可以在单线程模式下处理更多的并发任务,它是一个异步IO框架,而异步IO其实是基于事件触发机制来实现异步回调的,在IO处理上主要采用了IO复用机制来实现非阻塞操作。在开始使用asyncio之前,需要先初步了解asyncio的一些核心知识点。

asyncio的核心是Eventloop(事件循环),它以Eventloop为核心来实现协程函数结果的回调。它提供了相关协程任务的注册、取消、执行及回调等方法来实现并发。

在Eventloop中执行的任务其实就是人们定义的各种协程对象。通常,每一个协程对象内部都会包含自身需要等待处理的IO任务。当Eventloop处理协程任务时,遇到需要等待处理的IO任务,会自动执行权限切换,自动去执行下一个协程任务。当上一个IO任务完成时,会在下一次事件循环返回最终等待结果的状态。这种多任务交替轮换的协同处理机制可以有效提高CPU的使用率,进而提升并发能力。

定义一个协程函数(Coroutine)的核心是async关键词。通过该关键词,人们可以把一个普通的函数转换为一个协程函数,转变后协程函数的运行就不像普通函数那样了,它需要依赖于上面提到的Eventloop。当对协程函数执行“协程函数()”时,“协程函数()”表示一个协程对象。此时执行“await协程函数()表示创建了对应的Task并放入循环事件(也可以通过asyncio.create_task()来创建Task),该Task就是协程函数要执行的逻辑。