【问题标题】:Django + WSGI: Refreshing Issues?Django + WSGI:令人耳目一新的问题?
【发布时间】:2009-10-28 09:06:04
【问题描述】:

我正在开发一个 Django 网站。我正在实时服务器上进行所有更改,只是因为这样更容易。问题是,它似乎时不时地喜欢缓存我正在处理的 *.py 文件之一。有时,如果我经常点击刷新,它会在旧版页面和新版页面之间来回切换。

我的设置或多或少类似于 Django 教程中描述的内容:http://docs.djangoproject.com/en/dev/howto/deployment/modwsgi/#howto-deployment-modwsgi

猜测它这样做是因为它启动了 WSGI 处理程序的多个实例,并且根据 http 请求被发送到哪个处理程序,我可能会收到不同版本的页面.重启apache好像可以解决问题,但是很烦人。

我真的不太了解 WSGI 或“MiddleWare”或任何请求处理的东西。我来自 PHP 背景,一切正常 :)

无论如何,解决这个问题的好方法是什么?运行 WSGI 处理程序是否会以“守护程序模式”缓解问题?如果是这样,我如何让它在守护程序模式下运行?

【问题讨论】:

    标签: django apache mod-wsgi


    【解决方案1】:

    在守护程序模式下运行进程将无济于事。以下是正在发生的事情:

    mod_wsgi 正在生成多个相同的进程来处理您的 Django 站点的传入请求。这些进程中的每一个都是它自己的 Python 解释器,并且可以处理传入的 Web 请求。这些进程是持久的(它们不会针对每个请求启动和拆除),因此单个进程可能会一个接一个地处理数千个请求。由于有多个进程,mod_wsgi 能够同时处理多个 Web 请求。

    每当执行“导入模块”时,每个进程的 Python 解释器都会加载您的模块(您的自定义 Python 文件)。在 django 的上下文中,当由于 Web 请求而需要新的 view.py 时会发生这种情况。加载模块后,它会驻留在内存中,因此您对文件所做的任何更改都不会反映在该进程中。随着越来越多的 Web 请求进入,该进程的 Python 解释器将简单地使用已加载到内存中的模块版本。您会看到刷新之间的不一致,因为您发出的每个 Web 请求都可以由不同的进程处理。一些进程可能在您的代码的早期版本中加载了您的 Python 模块,而其他进程可能在以后加载了它们(因为这些进程没有收到 Web 请求)。

    简单的解决方案:每当您修改代码时,重新启动 Apache 进程。大多数时候,这就像从 shell “/etc/init.d/apache2 restart” 以 root 身份运行一样简单。我相信简单的重新加载也可以,速度更快,“/etc/init.d/apache2 reload”

    守护程序解决方案:如果您在守护程序模式下使用 mod_wsgi,那么您需要做的就是触摸(unix 命令)或修改您的 wsgi 脚本文件。为了澄清 scrompt.com 的帖子,对 Python 源代码的修改不会导致 mod_wsgi 重新加载您的代码。仅当修改了 wsgi 脚本文件时才会重新加载。

    最后一点要注意:为了简单起见,我只谈到 wsgi 使用进程。 wsgi 实际上在每个进程中使用线程池。我觉得这个细节与这个答案无关,但您可以通过阅读 mod_wsgi 了解更多信息。

    【讨论】:

    • 很好的解释!谢谢。这个线程池是否比 PHP 正在做的任何事情都有利/更快?
    • 使用多线程时,您必须与 Python GIL 抗衡。因此,对于计算密集型请求处理程序代码,您可能会因无法在一个进程中利用多个 CPU/内核而受苦。如果代码正在访问释放 GIL 的数据库和其他模块,则问题不大。无论如何,比这复杂得多。建议您阅读“blog.dscpl.com.au/2007/09/…”。
    • 顺便说一句,守护程序模式可以提供帮助,因为它允许您运行代码监视器,如其他响应中引用的 mod_wsgi 文档中所述。这样,对 Python 代码的任何更改,不仅仅是对 WSGI 脚本文件的更改,都可以自动触发守护进程组的重启。
    【解决方案2】:

    您可以通过不在实时服务器上编辑代码来解决此问题。说真的,没有任何借口。使用版本控制在本地进行开发,如果必须,从实时签出运行您的服务器,并使用一个提交后挂钩来签出您的最新版本并重新启动 Apache。

    【讨论】:

    • 是的,但有时 prod 环境的行为与内置开发服务器不同,所以别无选择:)
    • @jujule:你可以在prod服务器上设置一个测试域,这样你就可以在本地测试你开发的东西。我想不出任何可以证明在产品服务器上编辑代码的借口。
    • 复制服务器环境的工作量太大了!我的服务器正在运行 ubuntu/apache2/postgres,而我的家用计算机使用的是 win7 ......我什至没有尝试安装其他两个。假设我确实运行了,我将如何将数据库迁移到生产环境?
    • 更不用说 apache 重启会导致宝贵的几秒钟的停机时间。
    • 人们在实时服务器上编码的原因有很多。否则你无权告诉他。请坚持主题。
    【解决方案3】:

    因为您在嵌入式模式下使用 mod_wsgi,您的更改不会被自动看到。您偶尔会看到它们,因为 Apache 有时会启动新的处理程序实例,这些实例会捕获更新。

    您可以使用守护程序模式解决此问题,如 here 所述。具体来说,您需要将以下指令添加到您的 Apache 配置中:

    WSGIDaemonProcess example.com processes=2 threads=15 display-name=%{GROUP}
    WSGIProcessGroup example.com
    

    【讨论】:

    • 我假设您可以将声明放在与 WSGIScriptAlias 相同的上下文中。
    • 这似乎完全没有效果,顺便说一句。
    • 你只是拯救了我的一天! :)
    【解决方案4】:

    阅读 mod_wsgi 文档,而不是依赖 Django 站点上包含的 mod_wsgi 托管的最少信息。特别是,阅读:

    http://code.google.com/p/modwsgi/wiki/ReloadingSourceCode

    这会告诉你源代码重载在 mod_wsgi 中是如何工作的,包括一个监视器,你可以使用它来实现与 Django runserver 相同的源代码重载。另请参阅有关如何将其应用于 Django 的讨论。

    http://blog.dscpl.com.au/2008/12/using-modwsgi-when-developing-django.html http://blog.dscpl.com.au/2009/02/source-code-reloading-with-modwsgi-on.html

    【讨论】:

      猜你喜欢
      • 2020-05-02
      • 2020-01-28
      • 2018-10-11
      • 2014-01-10
      • 1970-01-01
      • 2011-06-27
      • 1970-01-01
      • 1970-01-01
      • 2017-07-23
      相关资源
      最近更新 更多