什么是Tornado和Mongodb阻塞和异步注意事项?

时间:2013-03-12 00:01:55

标签: python asynchronous tornado pymongo python-multithreading

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

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

问题1:连接池

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

问题2:多线程Mongo呼叫

以下常见问题:

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

规定:

  

目前没有很好的方法可以结合使用PyMongo   龙卷风或扭曲。 PyMongo提供内置连接池,所以   这些框架的一些好处可以通过以下方式实现   编写共享MongoClient的多线程代码。

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

问题3:多个实例

最后,我可能只是在创作吗?我应该通过运行Tornado的单线程实例来快捷方式,然后每个核心启动3-4个实例吗? (上面的FAQ参考似乎暗示了这一点)

毕竟不是python中的GIL会导致有效的不同进程吗?或者Tornado的“非阻塞”方面还有其他性能考虑因素(正负)吗? (我知道这在I / O方面是非阻塞的,如下所示:Is Tornado really non-blocking?

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

3 个答案:

答案 0 :(得分:2)

据我所知,网络服务器有两个概念:

  1. 基于线程(apache)
  2. 事件驱动(龙卷风)
  3. 你有使用python的GIL,GIL对线程不好,而事件驱动是一个只使用一个线程的模型,所以请选择事件驱动。

    Pymongo将阻止龙卷风,所以这里有建议:

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

        

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

      NB:抱歉,如果没有话题,但是句子:

        

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

      应该从文档中删除

      ,Mongotor和Motor以完美的方式工作(尤其是Motor)。

答案 1 :(得分:0)

你还知道电机吗? :http://emptysquare.net/blog/introducing-motor-an-asynchronous-mongodb-driver-for-python-and-tornado/ 它由杰森戴维斯撰写,他是pymongo的合着者

答案 2 :(得分:0)

虽然问题已经过时,但我觉得答案并不能完全解决用户提出的所有问题。

  

如果从单个线程运行单个MongoClient实例,那么确实没有" pool"因为任何时候只能打开一个连接?

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

  

最后,我可能只是在创作吗?我应该通过运行Tornado的单个线程实例来快捷方式,然后每个核心启动3-4个实例吗?

不,你不是!创建多个线程比多个线程的资源密集程度更低。

  

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

GIL仅阻止多个线程同时访问解释器。不会阻止多个线程同时执行I / O.事实上,asyncio的运动是如何实现异步性的。

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