在国外论坛看到一个老外关于 tornado的一些非堵塞模块原理性的讲述,一刹那间明了了很多。 so 通过自己的理解,简单实现了下一个简单的非堵塞模块。
嗯哼,原文地址是,blog.xiaorui.cc
当然实现的方法,还是存在点问题的, 但是最少流程是跑通了。 我在用ab做测试的时候,会发现数据已经进入到ioloop里面,但是逻辑堵塞到我们调用的函数上。
下一步再写一个,tornado redis brpop的非堵塞模块。
咱们先来看看,tornado的那个异步的装饰器@gen.coroutine,到底做了什么事情?
def _make_coroutine_wrapper(func, replace_callback): @functools.wraps(func) def wrapper(*args, **kwargs): runner = None future = TracebackFuture() #创建了一个新的Future对象,这货就是Future. if replace_callback and 'callback' in kwargs: callback = kwargs.pop('callback') IOLoop.current().add_future( future, lambda future: callback(future.result())) #当future执行完就把callback加入ioloop. try: result = func(*args, **kwargs) #调用被装饰函数 except (Return, StopIteration) as e: result = getattr(e, 'value', None) except Exception: future.set_exc_info(sys.exc_info()) return future else: if isinstance(result, types.GeneratorType): #如果被装饰函数被调用后产生一个Generator就用一个Runner来让future调用result. runner = Runner(result, future) runner.run() return future future.set_result(result) return future return wrapper
这个是tornado的demo,异步的逻辑需要你用yield async来生成的。
import tornado.ioloop import tornado.web from tornado.gen import coroutine import torasync import time def test(a): time.sleep(3) print 'coming' return 'ok' class MainHandler(tornado.web.RequestHandler): @coroutine def get(self): result = yield tornasync.async(test, "xiaorui.cc") self.write("%s" % result ) application = tornado.web.Application([ (r"/", MainHandler), ]) if __name__ == "__main__": application.listen(8888) tornado.ioloop.IOLoop.instance().start()
from tornado.concurrent import TracebackFuture from tornado.ioloop import IOLoop def async(task, *args, **kwargs): callback = kwargs.pop("callback", None) if callback: IOLoop.instance().add_future(future, lambda future: callback(future.result())) result = task(*args,**kwargs) IOLoop.instance().add_callback(_on_result, result, future) return future def _on_result(result, future): # if result is not ready, add callback function to next loop, if result: future.set_result(result) else: IOLoop.instance().add_callback(_on_result, result, future)
这个好像如果两次请求不同的sleep时间。首先请求sleep 6s。再请求sleep 2s。。。第二个请求还是堵塞了吧
恩
….
请教下,是不是在tornado下任何逻辑逻辑都要改成非堵塞的?
这个不错