为什么龙卷风异步不起作用

时间:2015-04-17 06:32:47

标签: python asynchronous tornado

今天,当我想让一些同步Python库异步运行时,它却无法正常工作。经过一系列测试后,我发现即使yield tornado.gen.sleep(N)同步运行。

这是我的代码:

import time
import tornado.web
import tornado.gen
import tornado.ioloop
import os


class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.render("test.htm")


class SleepHandler(tornado.web.RequestHandler):
    def get(self):
        time.sleep(2)
        self.write("Good morning!")


class YSleepHandler(tornado.web.RequestHandler):
    @tornado.gen.coroutine
    def get(self):
        yield tornado.gen.sleep(2)
        self.write("Good morning!")


def main():
    app = tornado.web.Application([
        (r"/sleep", SleepHandler),
        (r"/ysleep", YSleepHandler),
        (r"/", MainHandler),
        ], debug=True, template_path=os.path.split(
            os.path.realpath(__file__))[0])
    app.listen(8888)
    try:
        tornado.ioloop.IOLoop.current().start()
    except:
        tornado.ioloop.IOLoop.current().stop()


if __name__ == "__main__":
    main()

我使用下面的代码测试异步函数是否有效(在test.htm中 - 为MainHandler模​​板文件):

for(var i = 0; i < 10; i++){
                $.get("/sleep");
            }
for(var i = 0; i < 10; i++){
                $.get("/ysleep");
            }

但最后,我得到了一个意外的result

问题是什么?我在Python2.7和Python3.4环境下都尝试过。

2 个答案:

答案 0 :(得分:1)

最后,通过在URL的末尾添加一些独特的无用参数来重新解决这个问题。

for(var i = 0; i < 10; i++){
                $.get("/sleep");
            }
for(var i = 0; i < 10; i++){
                $.get("/ysleep");
            }

如果您使用上面的代码测试结果,您将收到与使用同步代码相同的结果(因为龙卷风将返回304未修改,它是一个同步函数。)。但如果使用下面的代码,将完全说明同步和异步之间的差异。

for(var i = 0; i < 10; i++){
                $.get("/sleep", {"random": Math.random()});
            }
for(var i = 0; i < 10; i++){
                $.get("/ysleep", {"random": Math.random()});
            }

答案 1 :(得分:0)

您看到此行为是因为协程中的 yield 有效地将控制权转移回Tornado的IOLoop。这并不意味着它将结果返回给客户端 - 只是它将控制权返回给Tornado,以便IOLoop不会被长时间运行的请求阻止。

这对你的代码产生的影响是Tornado会在SleepHandler运行时阻塞,而在YSleepHandler运行时它不会阻塞。在这两种情况下,仅当您的处理程序调用 self.write()时,响应才会返回给客户端,但在YSleepHandler的情况下,当处理程序运行时,其他请求可以被处理,因为IOLoop是没有阻止。