django + mod_wsgi需要线程编程规则吗?

时间:2012-10-25 19:21:02

标签: python django thread-safety mod-wsgi

我们将mod_wsgi下的第一个django应用程序推广为

`WSGIDaemonProcess our-appname processes=6 threads=15'`

我们正在讨论我们的Python代码以及它使用的Redis和Postgres库是否需要是线程安全的。

从我在阅读mod_wsgi文档时可以看出,即使apache worker正在使用多个 apache 线程处理请求,我们的 python 代码也适用于所有意图和目的单线程的。我没有在mod_wsgi文档上看到任何警告“小心!!你现在必须担心全局数据和线程安全!”但也没有明确的“不要担心线程没有任何问题”。

我们在python代码中没有使用线程显式做任何事情,在我们编写的任何内容中都没有提到它们。

但是有些人认为,由于我们正在运行threads=15,我们现在处于多线程世界。

有人能澄清这里到底发生了什么吗?我们的Python代码现在是否通过相同的数据执行多个执行线程,而不是之前,不是吗?

3 个答案:

答案 0 :(得分:6)

是的,显然你正在运行多线程应用程序,如果你不关心全局变量,类属性等会产生问题

如果您需要保留全局内容,请将其保留在线程本地存储中。

以下是modwsgi doc, Building_A_Portable_Application

的引用
  

3。应用程序必须是可重入的,或者简单地说,可以同时由多个线程同时调用。数据哪个   需要存在请求的生命,需要存储为   基于堆栈的数据,线程本地数据或缓存在WSGI应用程序中   环境。实际应用程序模块中的全局变量   不能用于此目的。

所以我认为你已经受到了足够的警告。

答案 1 :(得分:1)

python解释器不是线程安全的,特别是因为引用计数,因此线程无法在同一进程空间中同时访问python对象。由于解释器受GIL(全局解释器锁)的保护,因此无法配置mod_wsgi以无意或有意地解决此问题。因此,您不必担心同时线程访问相同内存对象(内存锁定等)的风险带来的特别棘手的线程安全问题。

某些Web服务器(例如带有gevent支持器的gunicorn)将同时在内存中具有多个线程,因此不需要在I / O上阻止单个进程(数据库访问,网络访问等)。这也可能是mod_wsgi的情况。但是,这是以这样的方式实现的,您不必在应用程序代码中担心它 - 如果您的应用程序在多处理中使用是安全的,那么在这种有限的非并发线程中使用它也应该是安全的。模型。

当然,您不能使用全局变量或在运行时动态编辑应用程序的某些部分,但如果您在Django中执行类似的操作,那么在您不必担心线程之前就会遇到问题。 Django和其他Web框架的设计使得数据作为请求传递,并作为响应传递,而不必担心该模型中的线程/进程安全性。

您需要担心并发访问数据存储(尤其是数据库条目),就像任何Web应用程序一样。在数据库访问方面采取防御措施。

答案 2 :(得分:1)

我认为安德鲁的回答有点误导。事实上CPython(注意还有其他Python实现,如Jython和PyPy)具有GIL并不意味着您不必担心您的代码是线程安全的!由于GIL,一个进程中的两个线程不能同时处于活动状态。但是通过在线程之间定期切换来模拟并行性。这样的上下文切换可以在程序执行期间随时发生。例如,如果模块foo包含“全局”变量x,则以下方法可能会输出2,3,4,......中的任何内容,具体取决于线程数执行相同的方法:

def bar():
    foo.x = 1
    # a context switch might happen here!
    foo.x = foo.x + 1
    # or here!
    print(foo.x)

实际上,您可以将mod_wsgi配置为使用max。 1个线程。然后你不必担心线程安全。但是程序的正确性取决于Web服务器的配置,这是一种非常不合适的情况。