当前位置:  开发笔记 > 编程语言 > 正文

如何让Tornado中的SQLAlchemy异步?

如何解决《如何让Tornado中的SQLAlchemy异步?》经验,为你挑选了2个好方法。

如何使SQLAlchemyTornadoasync?我在async mongo示例中找到了MongoDB的示例,但我找不到类似motor的内容SQLAlchemy.有没有人知道如何SQLAlchemy执行查询tornado.gen(我在MySQL下面使用SQLAlchemy,目前我的处理程序从数据库读取并返回结果,我想使这个异步).



1> zzzeek..:

ORM非常适合显式异步编程,也就是说,程序员必须在任何使用网络访问的情况下产生显式回调.这样做的主要原因是ORM广泛使用延迟加载模式,这种模式或多或少与显式异步不兼容.代码看起来像这样:

user = Session.query(User).first()
print user.addresses

实际上会发出两个单独的查询 - 一个是当你说first()要加载一行时,另一个是你说的user.addresses,如果该.addresses集合尚未存在或已经过期.从本质上讲,几乎所有处理ORM结构的代码都可能会阻塞IO,所以你会在几秒钟之内进入广泛的回调意向 - 更糟糕的是,绝大多数代码行实际上不会阻塞IO,因此,将回调连接在一起以进行简单的属性访问操作的所有开销将使您的程序效率大大降低.

显式异步模型的一个主要问题是它们为复杂系统增加了巨大的Python函数调用开销 - 不仅在面向用户方面,就像延迟加载一样,而是在内部方面以及系统如何提供围绕Python数据库API(DBAPI).对于SQLAlchemy来说,即使拥有基本的异步支持,也会对绝大多数不使用异步模式的程序造成严重的性能损失,甚至是那些不是高度并发的异步程序.考虑SQLAlchemy或任何其他ORM或抽象层,可能具有如下代码:

def execute(connection, statement):
     cursor = connection.cursor()
     cursor.execute(statement)
     results = cursor.fetchall()
     cursor.close()
     return results

上面的代码执行似乎是一个简单的操作,在连接上执行SQL语句.但是使用完全异步DBAPI(如psycopg2的异步扩展),上面的代码至少会在IO上阻塞三次.所以用显式异步样式编写上面的代码,即使没有使用异步引擎并且回调实际上没有阻塞,也意味着上面的外部函数调用至少变成了三个函数调用,而不是一个,不包括强加的开销通过显式异步系统或DBAPI调用自身.因此,一个简单的应用程序会自动给出围绕语句执行的简单抽象的函数调用开销的3倍的惩罚.而在Python中,函数调用开销就是一切.

出于这些原因,我仍然对围绕显式异步系统的炒作感到兴奋,至少在一定程度上,有些人似乎想要对所有事情进行异步处理,例如提供网页(请参阅node.js).我建议使用隐式异步系统,最明显的是gevent,在这里你可以获得异步模型的所有非阻塞IO优势,而不是显式回调的结构冗余/缺点.我继续尝试理解这两种方法的用例,所以我对显式异步方法作为所有问题的解决方案的吸引力感到困惑,就像你在node.js中看到的那样 - 我们正在使用脚本语言减少详细程度和代码复杂性的第一个地方,以及提供网页这样的简单事物的显式异步似乎什么都不做,只是添加样板,如果阻塞IO甚至是一个问题,那么也可以通过gevent或类似方法实现自动化.这样的情况(大量的高容量网站使用同步IO模型做得很好).基于Gevent的系统经过生产验证,并且它们的受欢迎程度正在增长,因此如果您喜欢ORM提供的代码自动化,您可能还希望采用像gevent这样的系统提供的async-IO-scheduling自动化.

更新:Nick Coghlan指出了他关于显式与隐式异步主题的伟大文章,这也是必须阅读的内容.而且我也更新了pep-3156现在欢迎与gevent的互操作性,扭转其先前所说的gevent不感兴趣的事实,这在很大程度上要归功于Nick的文章.因此,一旦集成了这些方法的系统可用,我将推荐将Tornado混合使用gevent作为数据库逻辑.


一如既往的答案......业务和持久性逻辑不需要非阻塞IO.如果您被迫使用强制所有内容"显式异步"的Web框架,那么最佳解决方案是a).使用普通的Web框架,如烧瓶或金字塔或b.使用线程池
自这个答案发布以来已经过去了4年.我想知道,zzzeek,或社区中的任何其他人.他们对ORM环境有什么重大改变,Tornado或gevent是否需要对此答案进行审核?我问,因为我在这里可能面临这个问题:/sf/ask/17360801/ to-use-sqla Bokeh服务器应用程序使用Tornado,我需要连接到db以从中检索信息.

2> Ander..:

我过去遇到过同样的问题,但是找不到可靠的Async-MySQL库.然而,使用Asyncio + Postgres有一个很酷的解决方案.您只需要使用aiopg库,它随附SQLAlchemy支持:

import asyncio
from aiopg.sa import create_engine
import sqlalchemy as sa


metadata = sa.MetaData()

tbl = sa.Table('tbl', metadata,
           sa.Column('id', sa.Integer, primary_key=True),
           sa.Column('val', sa.String(255)))

@asyncio.coroutine
def go():
    engine = yield from create_engine(user='aiopg',
                                      database='aiopg',
                                      host='127.0.0.1',
                                      password='passwd')

    with (yield from engine) as conn:
        yield from conn.execute(tbl.insert().values(val='abc'))

        res = yield from conn.execute(tbl.select().where(tbl.c.val=='abc'))
        for row in res:
            print(row.id, row.val)


loop = asyncio.get_event_loop()
loop.run_until_complete(go())

推荐阅读
郑小蒜9299_941611_G
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有