已同步是什么意思啊 同步是什么( 二 )


一个异步应用程序完全运行在单个进程或线程中 , 这可以说是令人吃惊的 。当然 , 这种类型的并发需要遵循一些规则 , 因此你不能让一个任务占用 CPU 太长时间 , 否则 , 剩余的任务会被阻塞 。为了异步执行 , 所有的任务需要定时主动暂停并将控制权返还给循环 。为了从异步方式获益 , 一个应用程序需要有经常被 I/O 阻塞的任务 , 并且没有太多 CPU 工作 。Web 应用程序通常非常适合 , 特别是当它们需要处理大量客户端请求时 。
在使用一个异步服务器时 , 为了最大化多 CPU 的利用率 , 通常需要创建一个混合方案 , 增加一个负载均衡器并在每个 CPU 上运行一个异步服务器 , 如下图所示:
Python 中实现异步的 2 种方法我敢肯定 , 你知道要在 Python 中写一个异步应用程序 , 你可以使用 asyncio package  , 这个包是在协程的基础上实现了所有异步应用程序都需要的暂停和恢复特性 。其中yield关键字 , 以及更新的async和await都是asyncio构建异步能力的基础 。
Python 生态系统中还有其它基于协程的异步方案 , 例如 Trio 和 Curio。还有 Twisted  , 它是所有协程框架中最古老的 , 甚至出现得比asyncio都要早 。
如果你对编写异步 Web 应用程序感兴趣 , 有许多基于协程的异步框架可以选择 , 包括 aiohttp 、 sanic 、 FastAPI 和 Tornado。
很多人不知道的是 , 协程只是 Python 中编写异步代码的两种方法之一 。第二种方法是基于一个叫做 greenlet 的库 , 你可以用 pip 安装它 。Greenlets 和协程类似 , 它们也允许一个 Python 函数暂停执行并稍后恢复 , 但是它们实现这点的方式完全不同 , 这意味着 Python 中的异步生态系统分成两大类 。
协程与 greenlets 之间针对异步开发最有意思的区别是 , 前者需要 Python 语言特定的关键字和特性才能工作 , 而后者并不需要 。我的意思是 , 基于协程的应用程序需要使用一种特定的语法来书写 , 而基于 greenlet 的应用程序看起来几乎和普通 Python 代码一样 。这非常酷 , 因为在某些情况下 , 这让同步代码可以被异步执行 , 这是诸如asyncio之类的基于协程的方案做不到的 。
那么在 greenlet 方面 , 跟asyncio对等的库有哪些?我知道 3 个基于 greenlet 的异步包: Gevent 、 Eventlet 和 Meinheld  , 尽管最后一个更像是一个 Web 服务器而不是一个通用的异步库 。它们都有自己的异步循环实现 , 而且它们都提供了一个有趣的“monkey-patching”功能 , 取代了 Python 标准库中的阻塞函数 , 例如那些执行网络和线程的函数 , 并基于 greenlets 实现了等效的非阻塞版本 。如果你有一些同步代码想要异步运行 , 这些包会对你有所帮助 。
据我所知 , 唯一明确支持 greenlet 的 Web 框架只有 Flask。这个框架会自动监测 , 当你想要运行在一个 greenlet Web 服务器上时 , 它会自我进行相应调整 , 而无需进行任何配置 。这么做时 , 你需要注意不要调用阻塞函数 , 或者 , 如果你要调用阻塞函数 , 最好用猴子补丁来“修复”那些阻塞函数 。
但是 , Flask 并不是唯一受益于 greenlets 的框架 。其它 Web 框架 , 例如 Django 和 Bottle  , 虽然没有 greenlets , 但也可以通过结合一个 greenlet Web 服务器并使用 monkey-patching 修复阻塞函数的方式来异步运行 。

推荐阅读