我正在学习编写一个可以处理数千个连接的后端服务器。在
我查看了一些示例代码,但发现它仍然是以同步逻辑编写的。在
例如:(take fromhttp://www.tornadoweb.org/en/stable/gen.html)
@gen.coroutine
def get(self):
http_client = AsyncHTTPClient()
response1, response2 = yield [http_client.fetch(url1), http_client.fetch(url2)]
print(response1.body, response2.body)
很明显,print
语句在得到两个回迁的响应之前无法执行,否则它将由于访问不存在的数据而引发异常。在
因此,它在最后两行之间必须有一个块,但是对于非块、异步、事件驱动的情况,块不是tornado是高亮显示的。。。然后,可以处理数千个连接?在
是的!在
在长时间运行的作业和缓慢的IO操作之间使用}这两种不同的模式很可能会混淆。我刚刚在那件事上犯了一个严重的错误。在
yield
和{在长期运行的工作中
next()
方法被反复调用,并且每次都执行一个工作单元。在coroutine
在运行,调度程序将逐个调用每个next()
方法,以便在两个作业之间共享CPU时间。因此它是作业之间的协作,因此称为coroutine
。在在慢IO操作中
next()
点只调用一次next()
方法。在yield
从执行IO操作开始,IO操作就委托给操作系统内核。当IO操作完成时,调度程序将添加一个回调,它将调用next()
方法。在next()
方法。这是由操作系统级的异步特性提供支持的,比如在IO完成时,epoll
,IOCP
到notiy调度器。在yield
来移交执行。IO完成后,它将通过从调度程序调用next()
继续执行。在因此,总而言之:
在长时间运行的作业中,一旦进程空闲,调度程序将调用每个
next()
方法。在慢IO操作中,
next()
方法在IO操作完成后只调用一次。我想如果你意识到这一点,你就会明白使用}实际上可以与{}具有相同的能力。在
yield
和{是,} ;它实际上是非阻塞的,并在
tornado
是异步的。您展示的示例是一个^{yield
调用时将控制释放回tornado事件循环。控件只在两个http_client.fetch
调用实际完成时返回get
函数。在这两个例子实际上在
tornado
中功能等效:还有一个协同程序版本:
^{pr2}$协同程序允许您编写异步代码,它看起来是同步的,可读性更强。当上面的代码命中} 对象。
yield
,get
将挂起并将http_client.fetch
返回给gen.coroutine
装饰器的^{gen.coroutine
修饰符有魔力,它可以安排fetch
调用返回的Future
的结果,以便在准备就绪后将其传递回get
。在相关问题 更多 >
编程相关推荐