有关Tornado 异步的讨论 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
geew
V2EX    Tornado

有关Tornado 异步的讨论

  •  
  •   geew 2013-11-11 10:21:06 +08:00 21108 次点击
    这是一个创建于 4406 天前的主题,其中的信息可能已经有所发展或是发生改变。
    最近开始用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
    其实同样的堵塞, 完全没有异步执行, 那以上的程序怎么改成异步的呢??
    35 条回复    2014-11-26 11:48:25 +08:00
    llbgurs
        1
    llbgurs  
       2013-11-11 10:34:46 +08:00
    只有io异步吧,数据库的library需要支持异步操作
    shiny
        2
    shiny  
    PRO
       2013-11-11 10:52:22 +08:00
    支持异步的库在这里可以找到: https://github.com/facebook/tornado/wiki/Links
    tornado 真用起来还是挺麻烦的。
    Veelian
        3
    Veelian  
       2013-11-11 10:52:50 +08:00 via iPhone
    time.sleep(10)会block你的应用的
    Shevckcccc
        4
    Shevckcccc  
       2013-11-11 10:54:53 +08:00
    楼主我遇到了跟你一样的问题,然后这是v2ex上的异步讨论 http://v2ex.com/t/85762#reply21
    binux
        5
    binux  
       2013-11-11 10:55:23 +08:00
    yield tornado.gen.Task 只是语法糖,需要函数修饰
    如果你才入门,想知道异步是怎么执行的话,不要看这种写法,去看callback的写法

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

    除此之外就是io库是异步的了,用得上的只有这个了
    cctvsmg
        8
    cctvsmg  
       2013-11-11 11:51:56 +08:00   1
    我试验过几个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
        9
    evan00  
       2013-11-11 12:35:26 +08:00
    @cctvsmg 可不分享下 你说的GAE里扣出的那块?
    cctvsmg
        10
    cctvsmg  
       2013-11-11 12:51:02 +08:00   1
    @evan00 才弄好,只跑了几个benchmark试验了下demo,等跑一段时间看看稳定性修改下bug,会公开的
    alsotang
        11
    alsotang  
       2013-11-11 13:20:48 +08:00
    在这个 JS 准备一统天下的年代,玩异步服务器还是来玩 Node 吧。
    fansgentle
        12
    fansgentle  
       2013-11-11 14:02:40 +08:00   2
    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
        13
    fansgentle  
       2013-11-11 14:06:24 +08:00
    @fansgentle 基本上都是手敲的格式还是这么乱,还有错别字 ...
    geew
        14
    geew  
    OP
       2013-11-11 14:15:12 +08:00
    @cctvsmg 公开之时勿忘我哈
    geew
        15
    geew  
    OP
       2013-11-11 14:18:14 +08:00
    @cctvsmg 感觉现在项目性能方面的问题比较大.
    ab测试 -c300 -n1000
    Requests per second: 64.20 [#/sec] (mean)

    中间还加了nginx. 测试机的测试结果
    geew
        16
    geew  
    OP
       2013-11-11 14:20:34 +08:00
    @fansgentle 很赞的回答 谢谢
    geew
        17
    geew  
    OP
       2013-11-11 15:41:38 +08:00
    @cctvsmg 单核情况下rps有30000?
    是Requests per second: 684.21 [#/sec] (mean)
    这个值吗?
    我随便用tornado+sqlalchemy, 单次请求访问一次数据库. ab 300的并发, 最多只能达到这个值.
    usoluyun
        18
    usoluyun  
       2013-11-12 01:21:40 +08:00
    @geew 瓶颈db那儿吧。什么事情不干,光是开关connection,小得vps能到300就不错了
    zenliver
        19
    zenliver  
       2013-11-12 16:24:26 +08:00
    fansgentle
        20
    fansgentle  
       2013-11-12 18:49:08 +08:00
    @zenliver 代码不到20行啊,赞,有空试下效果
    zenliver
        21
    zenliver  
       2013-11-12 22:00:36 +08:00
    @fansgentle 程序随小, 五脏俱全,,,呵呵
    geew
        23
    geew  
    OP
       2013-11-22 14:46:47 +08:00
    @cctvsmg 少年 说好的ORM呢 想研究研究下 谢谢了
    cctvsmg
        24
    cctvsmg  
       2013-11-22 15:08:05 +08:00   1
    @geew 可以先研究研究peewee 和 umysqldb相结合,另外https://github.com/BeanYoung/peewee这个版本加进去了connection pool,ndb那个因为是菲关系型的orm还在试验中。
    geew
        25
    geew  
    OP
       2013-11-22 17:49:23 +08:00
    @justfly 使用celery的话只要 pip install tornado-celery就行了吗?
    import tcelery 来用的话会有这个错误:
    怎么 AttributeError: 'module' object has no attribute 'celery_task'

    tcelery里面没有celery_task这个东西呢??
    justfly
        26
    justfly  
       2013-11-22 20:55:48 +08:00   1
    @geew 新版本问题吧,是我引用的代码,celery依赖环境很多,我没有测试。你可以看一下这里的介绍:https://github.com/mher/tornado-celery

    不出意外你要启动一个单独的 celery 进程来专门处理这些异步job的。像这样:http://docs.celeryproject.org/en/latest/getting-started/first-steps-with-celery.html

    请求不是非常频繁的话用线程吧,依赖少一些,线程池大小要自己把握,毕竟不配置的话默认linux一个线程8M 内存
    geew
        27
    geew  
    OP
       2013-11-25 11:33:10 +08:00
    @zenliver 试过了 但要tornado3.x以上才能运行的
    geew
        28
    geew  
    OP
       2013-11-25 11:34:57 +08:00
    @justfly 嗯 还得研究研究下. 你引用的代码是使用了这个的https://github.com/mayflaver/tornado-celery . tornado 2.x不能运行. 3x才行

    有用tornado-celery tornado版本2.2的demo么, 照着官方的做总是出现各种各样的问题
    geew
        29
    geew  
    OP
       2013-11-25 12:01:19 +08:00
    @justfly
    @fansgentle
    有些浮躁了 我还是好好看看下celery的文档再说
    neoz
        30
    neoz  
       2014-06-21 13:31:27 +08:00
    @fansgentle 请问tornado的request_time应该怎么实现?
    fansgentle
        31
    fansgentle  
       2014-06-25 10:05:16 +08:00
    自己写的话可以这样

    class BaseHandler(tornado.web.RequestHandler):

    def initialize(self):
    self._start_time = time.time()

    def on_finish(self):
    self._finish_time = time.time()
    # deal request_time

    另tornado.web.RequestHandler实例的request属性有request_time方法:
    https://github.com/tornadoweb/tornado/blob/4e9de2e43f50ae8a5317d4287d592904cf39a9e5/tornado/httputil.py#L399
    fansgentle
        32
    fansgentle  
       2014-06-25 10:07:28 +08:00
    @neoz 以上
    sujunj2005
        33
    sujunj2005  
       2014-11-26 11:27:36 +08:00
    这么一说tornado易用性没有这么好啊,亏我们还在用tornado+motor
    geew
        34
    geew  
    OP
       2014-11-26 11:47:52 +08:00
    @sujunj2005 好不好各有评判吧 不过要是真正的用好tornado 也是挺不容易的
    geew
        35
    geew  
    OP
       2014-11-26 11:48:25 +08:00
    @sujunj2005 http://www.nowamagic.net/academy/detail/13321030 看源码去吧 估计会有其他的体会
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1296 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 23:57 PVG 07:57 LAX 15:57 JFK 18:57
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86