在Django + uWsgi项目中运行时,PyMongo查找返回空/部分游标

Sha*_*ism 10 django mongodb pymongo pymongo-3.x

我们使用Django&mongoDB(PyMongo驱动程序)开发了一个REST API .问题是,在对API端点的一些请求中,PyMongo游标返回一个部分响应,其中包含的文档少于应有的数量(但它是一个完全有效的JSON文档).

让我用我们的一个观点的例子来解释它:

def get_data(key):
    return collection.find({'key': key}, limit=24)

def my_view(request):
    key = request.POST.get('key')
    query = get_data(key)
    res = [app for app in query]
    return JsonResponse({'list': res})
Run Code Online (Sandbox Code Playgroud)

我们确信有超过8000个文档与查询匹配,但在某些调用中,我们得到的结果少于24个(甚至为零).我们调查的第一个问题是MongoClient我们的代码中有多个定义.通过解决这个问题,问题的发生次数减少了,但我们仍然在很多电话中都有这种情况.

在所有这些调查之后,我们设计了一个测试,其中我们同时向服务器发出了16个异步请求.通过这种方法,我们可以重现这个问题.在这16个请求中,每个请求中有6-8个具有部分结果.运行此测试后,我们将uWsgi进程数减少到6并重新启动服务器.所有结果都很好,但在服务器上施加了另一个重负载后,问题再次出现.此时,我们重新启动了uwsgi服务,一切都很好.通过最后一个实验,我们现在有一个线索,即当uwsgi服务开始运行时,一切正常,但经过一段时间和重负载后,服务器开始再次返回部分或空的结果.我们最近的调查是使用python manage.pywith 运行APIDEBUG=False在这种情况下,我们在一段时间后再次遇到问题.

我们无法弄清楚问题是什么以及如何解决.我们可以想到的一个原因是Django在完成之前关闭了pymongo的连接.因为返回的结果是有效的JSON.

我们的堆栈是:

  • nginx(未启用缓存)
  • uWsgi
  • MemCached(在调试过程中禁用)
  • Django(python 3上的v1.8)
  • PyMongo(v3.0.3)

非常感谢您的帮助.

更新:

Mongo版本:

db version v3.0.7
git version: 6ce7cbe8c6b899552dadd907604559806aa2e9bd
Run Code Online (Sandbox Code Playgroud)
  • 我们正在运行单个mongod实例.没有分片/复制.
  • 我们正在使用此代码段创建连接:

    con = MongoClient('localhost',27017)

更新2

Pymongo问题跟踪器中的主题线程.

Sha*_*ism 2

Pymongo 游标不是线程安全元素。因此,像我在多线程环境中所做的那样使用它们将导致我所描述的问题。另一方面,Python 的list操作大多是线程安全的,像这样更改代码片段将解决问题:

def get_data(key):
    return list(collection.find({'key': key}, limit=24))

def my_view(request):
    key = request.POST.get('key')
    query = get_data(key)
    res = [app for app in query]
    return JsonResponse({'list': res})
Run Code Online (Sandbox Code Playgroud)