Ternado,同步与异步
总所周知,Ternado是一个非阻塞的Web服务器,很多人因为它的高效性,因为它的短小精悍而选择使用它。同样的理由,我们也选择了使用它。但是在用了它快一年后的今天,我才发现我根本就没有使用到它真正的异步特性。
首先,什么是阻塞?什么是非阻塞?以下两张图就应该能够解释一切了:
那么按照Ternado中给出的示例代码的执行结果是什么?
你会惊讶的发现,它官网给出的所有代码执行出来的结果都是同步的。也就是说你根本无法真正的启用它的异步特性。
做一个简单的试验,运行这个程序,然后访问 http://127.0.0.1:8888/test/ ,页面会卡住10秒,然后在这卡住的10秒内,你访问一下http://127.0.0.1:8888/ 如果它真的是一个非阻塞的系统,它应该快速的告诉你Hello, world……但是事实却并不是如此,系统一直到那10秒的程序运行完成,才会给你返回你想要的Hello,World。
原因并不是在于Ternado本身,而是在于客户端程序员的我们。因为所有的异步架构中,所有的代码必须要全部都是异步的,而get中的代码是同步的,所以必然没办法实现ternado的真正异步非阻塞。
所以,还是像erlang一样善用进程吧,毫不吝啬的使用它们吧。
这才是真正的异步代码,这个时候再试试看同时访问 http://127.0.0.1:8888/test/ 和http://127.0.0.1:8888/ 吧
首先,什么是阻塞?什么是非阻塞?以下两张图就应该能够解释一切了:
阻塞(同步)模型
非阻塞(异步)模型
两个模型从图形上理解起来都很容易。一个是顺序执行,另外一个则是打乱顺序执行。
理论上讲,非阻塞的模型并不一定绝对拥有最佳的效率,但是它在外部调用频繁、涉及到多处IO请求的状况下,它理论上拥有更高的执行效率,因为它在同步处于等待状态下的时间段内它也依然在尽力的压榨着CPU的运算能力。而异步模型最大的问题就是频繁的在多个进程(线程)中调度过程中的CPU消耗。
那么按照Ternado中给出的示例代码的执行结果是什么?
你会惊讶的发现,它官网给出的所有代码执行出来的结果都是同步的。也就是说你根本无法真正的启用它的异步特性。
import time import tornado.ioloop import tornado.web class MainHandler(tornado.web.RequestHandler): def get(self): self.write("Hello, world") class BlockHandler(tornado.web.RequestHandler): def get(self): time.sleep(10) self.write("Final Over") application = tornado.web.Application([ (r"/", MainHandler), (r"/test/", BlockHandler), ]) if __name__ == "__main__": application.listen(8888) tornado.ioloop.IOLoop.instance().start()
做一个简单的试验,运行这个程序,然后访问 http://127.0.0.1:8888/test/ ,页面会卡住10秒,然后在这卡住的10秒内,你访问一下http://127.0.0.1:8888/ 如果它真的是一个非阻塞的系统,它应该快速的告诉你Hello, world……但是事实却并不是如此,系统一直到那10秒的程序运行完成,才会给你返回你想要的Hello,World。
原因并不是在于Ternado本身,而是在于客户端程序员的我们。因为所有的异步架构中,所有的代码必须要全部都是异步的,而get中的代码是同步的,所以必然没办法实现ternado的真正异步非阻塞。
所以,还是像erlang一样善用进程吧,毫不吝啬的使用它们吧。
这才是真正的异步代码,这个时候再试试看同时访问 http://127.0.0.1:8888/test/ 和http://127.0.0.1:8888/ 吧
import threading import time import tornado.ioloop import tornado.web from tornado.web import asynchronous class MainHandler(tornado.web.RequestHandler): def get(self): self.write("Hello, world") class BlockHandler(tornado.web.RequestHandler): @asynchronous def get(self): Factory(self.after_done).start() def after_done(self, value): self.finish(value) class Factory(threading.Thread): def __init__(self, callback=None): super(Factory, self).__init__() self.callback = callback def run(self): time.sleep(10) self.callback('Final Over') application = tornado.web.Application([ (r"/", MainHandler), (r"/test/", BlockHandler), ]) if __name__ == "__main__": application.listen(8888) tornado.ioloop.IOLoop.instance().start()
评论
发表评论