声明
本文只讨论如何写针对网络请求的事件循环
前置要求
- 使用过asyncio或者类似的库,对协程这个概念有一些了解。
- 协程是有状态的。另外进程也有状态的,比如挂起,就绪,运行等。。。
time.sleep发生了什么
来思考这样一个情形,你写了一个程序,这个程序会sleep N秒,但是这个会影响到你接收QQ消息吗?显然不会!!!
你可能觉得进程之间资源不共享,所以A进程的操作不会影响到QQ进程。那回到原点,操作系统又是怎么知道你刚好休眠了N秒的。
这个问题我没有查过,有经验的朋友可以留言交流。但是我通过strace去跟踪这样的程序,我发现在系统调用中调用了select函数。
(补充:strace
是一个命令,可以通过yum install strace
来安装,基本用法是strace -p $进程id$
)
回到标题,所谓事件循环,本质上其实是要我们实现一个操作系统的进程调度机制。只不过这个调度发生在用户态。
什么是事件循环
- 事件
- 循环
没错,就是这么简单,事件
加上循环
就构成了事件循环。一般事件循环用于处理网络中,即io操作中。因为网络很慢,所以当顺序性的执行网络请求,比如使用requests库的时候会比aiohttp慢很多。
怎样写事件循环
- 事件
- 需要能够提供一个方法,注册到循环中去,让循环去监听其状态,通常来说,这个可以是套接字的
fileno
- 提供一些
逻辑
,供给循环去回调
- 需要能够提供一个方法,注册到循环中去,让循环去监听其状态,通常来说,这个可以是套接字的
- 循环
- select、epoll、poll等方法去监听fileno的可读可写
- 当发现状态改变时,即有可读可写的fileno时,去调用这个fileno归属对象的
逻辑