6

我有一个多线程 django 应用程序,它在单独的线程中创建一些对象以便更快地返回。创建的对象仅用于跟踪用户所做的事情,并且对时间不敏感。

以前的视图函数看起来像这样:

def foo(request):
    #... do important computation...
    bar(x, y, z)
    return HttpResponse()

这里一切正常,但是当我将其更改为这样并使用线程时:

def foo(request):
    #... do important computation...
    thread = Thread(target=bar, args=(x, y, z))
    thread.start()
    if testing_mode:
        thread.join()
    return HttpResponse()

第二个版本失败。这一切都是使用TransactionTestCasemySQL 完成的。

有任何想法吗?

4

1 回答 1

11

使用线程来卸载请求并不是一个好主意。陷阱多,好处少。主要问题(您的问题与这些有关)是:

  • Django 中的每个线程都使用单独的数据库连接,因此:
    • 你失去了交易的好处
    • 您必须在线程中手动关闭连接
    • 如果您没有以正确的方式关闭线程中的连接(而且很难做到正确),您将有数百个与数据库的打开连接,这会给您带来问题
    • 你有测试问题,因为测试框架在数据库连接上做了一些技巧,它不能在从线程连接上做
  • 翻译框架在线程中不起作用
  • 如果 wsgi 服务器决定重新加载,您的线程可能会被提前终止,但没有请求处理
  • Django 错误处理不适用于线程

正确的方法是:

  • 优化您的代码以更快地处理请求或
  • 使用 Celery 或 RQ 之类的任务系统将您的工作卸载到后台(这有一些上述问题,但更直接)。

PS。不要尝试设置 Celery 或 RQ 进行测试。您应该只模拟任务并单独测试它。

于 2013-07-07T12:23:48.087 回答