3

我正在与 Mongodb 一起运行 Tornado Web 服务器(使用 pymongo 驱动程序)。我正在尝试做出架构决策以最大限度地提高性能。

当一起使用 Tornado 和 pymongo 时,我有几个关于结果应用程序的阻塞/非阻塞和异步方面的子问题:

问题一:连接池

pymongo.mongo_client.MongoClient对象似乎自动实现了一个连接池。“连接池”的预期目的是为了让我可以从不同的线程同时访问 mongodb?如果使用单个线程中的单个 MongoClient 实例运行,是否真的没有“池”,因为任何时候都只会打开一个连接?

问题二:多线程Mongo调用

以下常见问题解答:

http://api.mongodb.org/python/current/faq.html#does-pymongo-support-asynchronous-frameworks-like-gevent-tornado-or-twisted

状态:

目前没有很好的方法将 PyMongo 与 Tornado 或 Twisted 结合使用。PyMongo 提供了内置的连接池,因此这些框架的一些好处可以通过编写共享 MongoClient 的多线程代码来实现。

所以我假设我只传递一个MongoClient对每个线程的引用?或者还有更多的东西吗?当每个线程产生结果时触发回调的最佳方法是什么?我是否应该让一个线程运行谁的工作是观察一个队列(python Queue.Queue)来处理每个结果,然后在 Tornado 中调用finish()左侧打开的对象?RequestHandler(当然tornado.web.asynchronous需要使用装饰器)

问题 3:多个实例

最后,有没有可能我只是在创作作品?我是否应该通过运行 Tornado 的单线程实例来简化事情,然后每个核心启动 3-4 个实例?(上面的常见问题参考似乎暗示了这一点)

毕竟,python 中的 GIL 不会导致有效的不同进程吗?或者 Tornado 的“非阻塞”方面是否有额外的性能考虑(正负)?(我知道这在 I/O 方面是非阻塞的,正如这里指出的那样: Tornado 真的是非阻塞的吗?

(附加说明:我知道 asyncmongo 在: https ://github.com/bitly/asyncmongo 但想直接使用 pymongo 而不是引入这个额外的依赖。)

4

3 回答 3

2

据我了解,网络服务器有两个概念:

  1. 基于线程 (apache)
  2. 事件驱动(龙卷风)

你有python的GIL,GIL不适合线程,事件驱动是一种只使用一个线程的模型,所以选择事件驱动。

Pymongo 会阻止龙卷风,所以这里有一些建议:

  1. 使用 Pymongo:使用它,并通过创建索引使您的数据库调用更快,但要注意;索引不适用于将扫描大量值的操作,例如:gte
  2. 使用AsyncMongo,似乎已经更新,但仍然不是所有 mongodb 功能。
  3. 使用Mongotor,这个就像是对 Asynchmongo 的更新,它有 ODM(对象文档映射器),拥有 MongoDB 所需的所有东西(聚合、副本集..),而你真正想念的唯一功能是 GridFS。
  4. 使用Motor,这是与 Tornado 一起使用的完整解决方案,它具有 GridFS 支持,并且它是 Tornado 的官方 Mongodb 异步驱动程序,它使用了Greenlet的 hack ,因此唯一的缺点是不与 PyPy 一起使用。

现在,如果您决定使用 Tornado 以外的其他解决方案,如果您使用 Gevent,那么您可以使用 Pymongo,因为据说

PyMongo 完全支持的唯一异步框架是 Gevent。

注意:对不起,如果跑题了,但是这句话:

目前没有很好的方法将 PyMongo 与 Tornado 结合使用

应该从文档中删除,Mongotor 和 Motor 以完美的方式工作(尤其是 Motor)。

于 2013-03-12T00:17:57.553 回答
1

虽然这个问题很老,但我觉得给出的答案并不能完全解决用户提出的所有问题。

如果使用单个线程中的单个 MongoClient 实例运行,是否真的没有“池”,因为任何时候都只会打开一个连接?

如果您的脚本不使用线程,这是正确的。但是,如果您的脚本是多线程的,那么在给定时间将打开多个连接

最后,有没有可能我只是在创作作品?我是否应该通过运行 Tornado 的单线程实例来简化事情,然后每个核心启动 3-4 个实例?

不,你不是!与多个分叉相比,创建多个线程占用的资源更少。

毕竟,python 中的 GIL 不会导致有效的不同进程吗?

GIL 只防止多个线程同时访问解释器。不阻止多个线程同时执行 I/O。事实上,这正是 motor with asyncio 实现异步性的方式。

它使用线程池执行器为每个查询生成一个新线程,并在线程完成时返回结果。

于 2017-07-24T04:38:21.580 回答
0

你也知道电机吗?: http://emptysquare.net/blog/introducing-motor-an-asynchronous-mongodb-driver-for-python-and-tornado/ 由 pymongo 的合著者 Jesse Davis 编写

于 2013-03-12T00:13:27.250 回答