首页 > 开发 > Python > 正文

tornado关于协程疑问

2017-09-06 19:23:22  来源:网友分享

tornado的协程,使用场景就究竟是什么呢?还有异步与协程最大的区别呢?tornado的异步非阻塞究竟是指网络操作的io呢,还是数据库这种io操作呢?

新手菜鸟...大家多多包涵

解决方案

同步和异步

异步的概念相对于同步,主要指程序执行的时候,普通函数调用与系统调用执行的运行状态。

在网络IO,通常需要系统调用accept获取连接和read获取数据。并且由于IO比较耗时,所以这两个系统调用到返回用户代码就存在阻塞和非阻塞。下面以read调用为例:

# 读取网络数据系统调用data = read()   # 执行任务AA.task()

对于同步模型,read函数调用之后,用户代码就无法往下执行A,用户进程就休眠了。操作系统进程则在进行缓存区数据的等待和读取,直到系统的read函数调用返回数据之后,用户进程才从休眠中醒来。然后执行A.task

对于异步模型,read函数调用之后,会向系统注册一个回调函数,用户进程并没有休眠,而是继续往下执行A.task,与此同时,操作系统的进程与同步模型时候的一样,也在等待数据和读取。只不过此时,操作系统的readA.task他们之间并没有先后顺序,而是各种执行各自的逻辑。看起来就是不同(异)的函数在执行(步)。当操作系统read执行完毕就会回调通知用户进程,并把数据返回。

异步和协程

异步和协程不能完全等同,他们的相似点都是函数执行的一种方式。协程,顾名思义就是协商程序(函数)。通常函数执行之后,要么返回,要么阻塞,阻塞一定条件之后返回。协程的函数则是函数执行到某个逻辑,设置一执行点,然后返回控制权,一旦某些条件满足了,再从刚设置的执行点进行接下来的函数逻辑,最后才返回。python中通常使用yield实现。这种执行流和异步很像。例如:

def get():    # 读取网络数据系统调用    data = yield read()       # 执行任务A    A.task(data)def post():    pass

协程和异步的实现效果类似,调用read后不会阻塞,而是返回控制权。对于get中,还是不能执行A.task,直到read数据到达,然后再从yield执行,最后执行A。这个流程与同步的差别在于,如果是同步,不仅是A无法执行,别的地方的代码也无法执行,比如 post中的逻辑。而协程的调用时候,get中的A.task无法执行,可是post中的其他代码是可以执行的。同步和异步对比中,看问题的观察点是get函数内,协程的观察点是get和post函数。

tornado的io

tornado的IO指的是处理网络连接的异步,即epoll(kqueue)方式处理连接。如果tornado的handler的单个请求中查询数据库,这里的IO就类似 get的read操作。既可以是同步,也可以是异步。只不过,如果这里使用了阻塞IO,那么整个tornado进程处理网络IO的时候,也会阻塞。