【问题标题】:How to stop WSGI from hanging apache如何阻止 WSGI 挂起 apache
【发布时间】:2010-11-16 11:20:36
【问题描述】:

我让 django 像这样通过 WSGI 运行:

<VirtualHost *:80>
    WSGIScriptAlias / /home/ptarjan/django/django.wsgi
    WSGIDaemonProcess ptarjan processes=2 threads=15 display-name=%{GROUP}
    WSGIProcessGroup ptarjan
    Alias /media /home/ptarjan/django/mysite/media/
</VirtualHost>

但如果我在 python 中这样做:

def handler(request) :
    data = urllib2.urlopen("http://example.com/really/unresponsive/url").read()

整个 apache 服务器挂起并且对这个回溯没有响应

#0  0x00007ffe3602a570 in __read_nocancel () from /lib/libpthread.so.0
#1  0x00007ffe36251d1c in apr_file_read () from /usr/lib/libapr-1.so.0
#2  0x00007ffe364778b5 in ?? () from /usr/lib/libaprutil-1.so.0
#3  0x0000000000440ec2 in ?? ()
#4  0x00000000004412ae in ap_scan_script_header_err_core ()
#5  0x00007ffe2a2fe512 in ?? () from /usr/lib/apache2/modules/mod_wsgi.so
#6  0x00007ffe2a2f9bdd in ?? () from /usr/lib/apache2/modules/mod_wsgi.so
#7  0x000000000043b623 in ap_run_handler ()
#8  0x000000000043eb4f in ap_invoke_handler ()
#9  0x000000000044bbd8 in ap_process_request ()
#10 0x0000000000448cd8 in ?? ()
#11 0x0000000000442a13 in ap_run_process_connection ()
#12 0x000000000045017d in ?? ()
#13 0x00000000004504d4 in ?? ()
#14 0x00000000004510f6 in ap_mpm_run ()
#15 0x0000000000428425 in main ()

在 Debian Apache 2.2.11-7 上。

同样地,我们能否受到保护:

def handler(request) :
    while (1) :
        pass

在 PHP 中,我会设置时间和内存限制。

【问题讨论】:

    标签: python django apache mod-wsgi


    【解决方案1】:

    这不是您想要的另一个指定的“死锁超时”,这是出于非常特殊的目的,在这种情况下无济于事。

    就尝试使用 mod_wsgi 功能而言,您需要 WSGIDaemonProcess 指令的“inactivity-timeout”选项。

    即便如此,这也不是一个完整的解决方案。这是因为 'inactivity-timeout' 选项专门用于检测守护进程的所有请求处理是否已停止,它不是每个请求的超时。如果守护进程是单线程的,它仅等同于每个请求的超时。除了帮助解除进程之外,如果在此期间根本没有请求到达,该选项还会产生重新启动守护进程的副作用。

    简而言之,在 mod_wsgi 级别没有办法让每个请求超时,这是因为在 Python 中没有真正中断请求或线程的方法。

    您真正需要实现的是应用程序代码中的 HTTP 请求超时。我不确定它在哪里以及是否已经可用,但请在 Google 上搜索“urllib2 套接字超时”。

    【讨论】:

    • 那么python就没有办法稳健运行了吗?哎呀...听起来我应该提交一个 mod_wsgi 功能请求。
    • 请求 mod_wsgi 功能请求毫无意义。无法中断处理请求的线程是 Python 的限制。
    • docs.python.org/library/thread.html#thread.interrupt_main 不提供中断线程的能力吗?还是我错过了什么?
    • 在Apache/mod_wsgi中线程是由Apache而不是Python创建的,请求通常不使用主线程,因此中断主线程的功能是没有用的。
    【解决方案2】:

    如果我很好地理解了这个问题,您希望在运行一些来自人们的随机脚本时保护 apache 不被锁定。好吧,如果您正在运行不受信任的代码,我认为您还有其他比 apache 更糟糕的事情要担心。

    也就是说,您可以使用一些配置指令来调整更安全的环境。下面这两个非常有用:

    • WSGIApplicationGroup - 设置 WSGI 应用程序所属的应用程序组。它允许为每个用户单独设置 - 同一应用程序组中的所有 WSGI 应用程序将在处理请求的进程的同一 Python 子解释器的上下文中执行。

    • WSGIDaemonProcess - 为运行应用程序配置不同的守护进程。守护进程可以以不同于 Apache 子进程通常运行的用户身份运行。该指令接受很多有用的选项,我将列出其中的一些:

      • user=name | user=#uidgroup=name | group=#gid

        定义应该作为守护进程运行的用户/组的 UNIX 用户和组名或数字用户 uid 或组 gid。

      • stack-size=nnn

        为与守护进程中由 mod_wsgi 创建的每个线程对应的堆栈分配的虚拟内存量(以字节为单位)。

      • deadlock-timeout=sss

        定义在检测到 Python GIL 上的潜在死锁之后,在关闭和重新启动守护进程之前允许经过的最大秒数。默认值为 300 秒。

    您可以阅读有关配置指令here 的更多信息。

    【讨论】:

    • 那么,300 秒超时是否意味着 apache 进程应该杀死我的 python 守护进程并重新启动它?因为整个 apache 被锁定,无法使用。我需要更多线程吗?较少的?更多进程?
    猜你喜欢
    • 2014-03-26
    • 1970-01-01
    • 2014-03-16
    • 2014-08-14
    • 1970-01-01
    • 1970-01-01
    • 2011-05-13
    • 2017-02-20
    • 1970-01-01
    相关资源
    最近更新 更多