Twisted + SQLAlchemy 的最佳实践

31 投票
4 回答
9033 浏览
提问于 2025-04-15 23:49

我正在写一个基于Twisted的守护进程。这个守护进程会有一个xmlrpc接口,这样我就可以轻松地和它沟通,也可以让其他进程根据需要和它交换数据。

这个守护进程需要访问数据库。我们最近的项目中一直在用SQL Alchemy来替代直接写SQL语句,主要是为了做一些基于Pylons的网页应用。

我们希望在这个应用中也能使用SQL Alchemy的库代码。那么该怎么做呢?当然,因为这个库是为Pylons应用写的,所以它的代码都是大家熟悉的同步风格,而所有的异步处理都是通过Pylons的线程、线程局部变量、作用域会话等方式自动处理的。

所以现在在Twisted中我有点困惑。我可以:

  1. 如果需要的SQL很简单,就直接写SQL,然后在Twisted中使用数据库连接池来执行数据库操作。
  2. 使用我们库中的对象和本身是阻塞的方法,在我的Twisted守护进程中偶尔阻塞一下。唉。
  3. 使用sAsync,这个库最后一次更新是在2008年,虽然可以部分重用我们已经定义的模型,但这并不能解决库代码也需要在Pylons中工作的情况。这个库能和最新版本的SQL Alchemy一起用吗?谁知道呢。这个项目看起来不错,为什么后来就没人维护了呢?
  4. 启动一个单独的子进程,让它处理库代码和所有的阻塞操作,结果再通过xmlrpc以YAML格式返回给我的守护进程。
  5. 使用deferToThread,然后在确保提前加载所有需要的对象后,清除返回的对象。对我来说,这听起来有点麻烦。

我现在还在用Python 2.5.4,所以还不能用2.6的功能,我觉得也不能通过“from future import”来获取新版本中的多进程模块。不过这也没关系,因为我们在进程间通信方面已经做得不错了。

所以我现在倾向于选择第4个选项,这样可以避免第1个选项中逻辑重复的问题,同时也能远离线程。

不过我第一次尝试会选择第2个选项,先让这个东西运行起来,然后如果发现某些操作可能会阻塞太久,再把对库代码的调用分离到一个单独的进程中。真可惜。也许结合Stackless Python和Twisted会有趣一些。

有没有更好的主意呢?

4 个回答

6

有一个叫做storm的分支,你可以直接用它和twisted一起工作(内部会处理一些线程的事情),可以在launchpad上找到,链接是https://code.launchpad.net/~therve/storm/twisted-integration。我用得挺顺手的。

可惜的是,sqlalchemy在实现上要复杂得多,特别是在检查它是否支持异步使用方面。如果你真的想用它,我建议你采用一种异步处理的方式,搭配一个存储的rpc层。

另外,如果你想尝试一些新东西,并且使用的是postgresql,最新的pyscopg2支持真正的异步使用(可以查看https://launchpad.net/txpostgres),而且storm的源代码也很简单,可以随便改改;-)

顺便提一下,你去年尝试的storm可能默认没有开启C扩展(现在最新版本里是有的),这可能是导致你速度慢的原因。

10

在这几年里,Alex Gaynor 创建了一个项目,叫做 https://github.com/alex/alchimia。这个项目可能是一个更好的中心库,可以用来和 SQLAlchemy 以及 Twisted 进行整合。

6

首先,我很遗憾地说,我只能赞同你的看法,twisted和SQLAlchemy的配合并不是很好。我之前用过这两者,感觉把它们放在一起会变得相当复杂,让我有些担心。

到目前为止,我知道的所有数据库集成层都使用了twisted的线程集成层。如果你想尽量避免使用这个,那你基本上就只能选择你列表中的第4点了。

不过,我也见过一些使用deferToThread()等方法的数据库连接代码,它们运行得非常好。

无论如何,如果你愿意考虑其他框架而不是SQLAlchemy,这里有一些建议:

DivMod团队在twisted和数据库集成方面做了一些初步的工作,基于Storm ORM(可以在网上搜索“storm orm”)。

你可以看看这个链接,里面有个例子:

http://divmod.readthedocs.org/en/latest/products/nevow/storm-approach.html

另外,去DivMod的网站看看他们的Axiom数据库层的源代码(可能对你直接没有用,因为它只支持Sqlite,但它的原理可能会对你有帮助)。

撰写回答