有关Tornado 异步的讨论

2013-11-11 10:21:06 +08:00
 geew
最近开始用tornado, 之前接触过的框架有django和flask. tornado的标榜就是异步, 但是在开发的过程中没怎么感觉到. 可能是我的使用问题吧.对异步这些东西的理解不是那么的透彻. 故此希望大家一起讨论下:

1.tornado异步的存在是需要程序中的各个处理均是异步的才行么? 比如访问数据库, 同步的访问的话tornado的异步貌似没有作用. 以及一些比较耗时间的任务, 都需要异步的写法才行, 并不是yield tornado.gen.Task(model.func, args=args)这样了之后就是异步执行了.

2.如果一成立的话每个函数都需要异步的写法, 问题就来了, 异步的程序怎么写呢? 我觉得这个问题挺大, 对异步的东西不是很了解. 还是比如访问数据库, 怎么做到异步的呢? 需要响应的数据库驱动支持么还是?

3.如果这样的话, tornado的优势在哪里呢? tornado的堵塞是会堵塞整个服务器, 好恐怖的赶脚.

PS: 好吧, 我就是想问问异步的程序怎么写的?
比如: yield tornado.gen.Task(model.func, args=args)
然后:
def func(args, callback=None):
time.sleep(10)
data = get_from_mysql(args)
if callback: callback(data)
return data
其实同样的堵塞, 完全没有异步执行, 那以上的程序怎么改成异步的呢??
20524 次点击
所在节点    Tornado
35 条回复
llbgurs
2013-11-11 10:34:46 +08:00
只有io异步吧,数据库的library需要支持异步操作
shiny
2013-11-11 10:52:22 +08:00
支持异步的库在这里可以找到: https://github.com/facebook/tornado/wiki/Links
tornado 真用起来还是挺麻烦的。
Veelian
2013-11-11 10:52:50 +08:00
time.sleep(10)会block你的应用的
Shevckcccc
2013-11-11 10:54:53 +08:00
楼主我遇到了跟你一样的问题,然后这是v2ex上的异步讨论 http://v2ex.com/t/85762#reply21
binux
2013-11-11 10:55:23 +08:00
yield tornado.gen.Task 只是语法糖,需要函数修饰
如果你才入门,想知道异步是怎么执行的话,不要看这种写法,去看callback的写法

callback的地方就是异步的,没有就是同步的
geew
2013-11-11 10:58:37 +08:00
@binux 真心想看 有推荐的一些例子么
binux
2013-11-11 11:01:30 +08:00
@geew http://www.tornadoweb.org/en/stable/httpclient.html#tornado.httpclient.AsyncHTTPClient

除此之外就是io库是异步的了,用得上的只有这个了
cctvsmg
2013-11-11 11:51:56 +08:00
我试验过几个tornado的异步驱动
比如umysqldb psycopg2 motor
比较神奇的用ab试验benchmark
结果表明这些异步驱动的性能很差

其中最神奇的是motor这货居然会卡死
motor用了greenlet,不知道是不是greenlet和tornado有不兼容的地方

最后采取的方案是.....
从GAE里面扣出来了一个叫ndb的orm
再把后端的数据库接口换成自己的mongodb服务器(也可以换成mysql)
运行的时候用的runtime环境是最新版的pypy2.2(性能爆表)

这个框架的性能大概情况:
如果tornado helloword 每次请求查询一次数据库
ab设置并发为100-300,单核情况下tornado的rps可以到3000左右
4核服务器跑个上万没问题

因为涉及的东西都是纯python的可以在bae sae gae heroku 等等平台上随便迁移
evan00
2013-11-11 12:35:26 +08:00
@cctvsmg 可不分享下 你说的GAE里扣出的那块?
cctvsmg
2013-11-11 12:51:02 +08:00
@evan00 才弄好,只跑了几个benchmark试验了下demo,等跑一段时间看看稳定性修改下bug,会公开的
alsotang
2013-11-11 13:20:48 +08:00
在这个 JS 准备一统天下的年代,玩异步服务器还是来玩 Node 吧。
fansgentle
2013-11-11 14:02:40 +08:00
Tornado的异步客户端直接写起来并不简单,可以参考官方的异步客户端tornado.httpclient.AsyncHTTPClient[https://github.com/facebook/tornado/blob/master/tornado/httpclient.py],要想使自己的服务是异步的,仅仅用上装饰器、yield是不够的,必须保证自己的写的客户端是异步的,即要用到tornado.ioloop.IOLoop,如 想让数据库操作支持异步,就可以自己仿照AsyncHTTPClient、在IOLoop的基础上实现一个数据库客户端。

要想写异步Tornado最简单的方法是用Celery: Distributed Task Queue[http://www.celeryproject.org],Tornado接到请求后把所有的业务逻辑处理、数据库操作及其他相关的IO操作等交给Celery来处理,不管耗时多长,处理完后异步返回,就能保证整个服务是完全异步的,当然,简单的不涉及太多IO或太复杂计算的操作还是建议用Tornado同步处理,因为把任务交给Celery的RabbitMQ通信会有一定网络IO开销。

Tornado的Celery适配器:https://github.com/mher/tornado-celery/
Celery的其他相关适配器:http://docs.celeryproject.org/en/latest/getting-started/introduction.html#framework-integration
异步的代码可以这样:
@tornado.web.asynchronous
@tornado.gen.coroutine
def get(self, *args, **kwargs):
response = yield tornado.gen.Task(celery_task_do_something.apply_async, args=[self.request.arguments])
self.finish(response.result)

Celery很赞,可以自己实践下,回用上瘾的 ^_^ ~~
fansgentle
2013-11-11 14:06:24 +08:00
@fansgentle 基本上都是手敲的格式还是这么乱,还有错别字 ...
geew
2013-11-11 14:15:12 +08:00
@cctvsmg 公开之时勿忘我哈
geew
2013-11-11 14:18:14 +08:00
@cctvsmg 感觉现在项目性能方面的问题比较大.
ab测试 -c300 -n1000
Requests per second: 64.20 [#/sec] (mean)

中间还加了nginx. 测试机的测试结果
geew
2013-11-11 14:20:34 +08:00
@fansgentle 很赞的回答 谢谢
geew
2013-11-11 15:41:38 +08:00
@cctvsmg 单核情况下rps有30000?
是Requests per second: 684.21 [#/sec] (mean)
这个值吗?
我随便用tornado+sqlalchemy, 单次请求访问一次数据库. ab 300的并发, 最多只能达到这个值.
usoluyun
2013-11-12 01:21:40 +08:00
@geew 瓶颈db那儿吧。什么事情不干,光是开关connection,小得vps能到300就不错了
zenliver
2013-11-12 16:24:26 +08:00
fansgentle
2013-11-12 18:49:08 +08:00
@zenliver 代码不到20行啊,赞,有空试下效果

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/88797

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX