在Apache Prefork/WSGI中共享Python解释器

Luk*_*hey 6 apache mod-wsgi wsgi apache2 django-wsgi

我试图在Apache(prefork)中使用WSGI运行Python应用程序,以便使用单个Python解释器.这是必要的,因为应用程序使用线程同步来防止发生竞争条件.由于Apache prefork产生了多个进程,因此代码最终不会在解释器之间共享,因此线程同步是无关紧要的(即每个线程只看到它自己的锁,这与其他进程没有关系).

这是设置:

  • Apache 2.0(prefork)
  • WSGI
  • Python 2.5

以下是相关的Apache配置:

WSGIApplicationGroup %{GLOBAL}
<VirtualHost _default_:80>

WSGIScriptAlias / /var/convergedsecurity/apache/osvm.wsgi

Alias /admin_media/ /var/www/html/admin_media/

<Directory /var/www/html/admin_media>
Order deny,allow
Allow from all
</Directory>

Alias /media/ /var/www/html/media/

<Directory /var/www/html/media>
Order deny,allow
Allow from all
</Directory>

</VirtualHost>
Run Code Online (Sandbox Code Playgroud)

这是我到目前为止所尝试的(没有一个工作):

  1. 添加WSGIApplicationGroup%{GLOBAL}
  2. 在虚拟主机中指定WSGIDaemonProcessWSGIProcessGroup:

    WSGIDaemonProcess osvm threads = 50
    WSGIProcessGroup osvm

有没有办法强制Apache prefork使用WSGI的单个Python解释器?这些文档似乎暗示您可以使用WSGIDaemonProcess和WSGIApplicationGroup选项,但Apache仍然为每个进程创建一个单独的Python解释器.

Gra*_*ton 9

您无法在UNIX系统上以嵌入模式运行WSGI应用程序,无论是prefork还是worker MPM,因为确实会有多个进程.看到:

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

创建一个由单个进程组成的守护进程组,并将WSGI应用程序委托给它,可以实现您想要的目标.如果它只是您正在讨论的一个已安装的WSGI应用程序,则甚至不需要使用WSGIApplicationGroup.如果你想完全确定,你也可以设置它.

因此,VirtualHost中的配置将是:

WSGIDaemonProcess osvm
WSGIProcessGroup osvm
WSGIApplicationGroup %{GLOBAL}

WSGIScriptAlias / /var/convergedsecurity/apache/osvm.wsgi
Run Code Online (Sandbox Code Playgroud)

虽然WSGIDaemonProcess的'processes = 1'明确表示创建了一个进程,但是不提供该选项,只是让它默认为一个进程.使用'processes'选项,即使对于一个进程也会看到'wsgi.multiprocess'设置为True.

我建议您使用以下简单的测试程序进行测试,而不是使用您的实际WSGI应用程序.

import cStringIO
import os

def application(environ, start_response):
    headers = []
    headers.append(('Content-Type', 'text/plain'))
    write = start_response('200 OK', headers)

    input = environ['wsgi.input']
    output = cStringIO.StringIO()

    print >> output, "PID: %s" % os.getpid()
    print >> output

    keys = environ.keys()
    keys.sort()
    for key in keys:
        print >> output, '%s: %s' % (key, repr(environ[key]))
    print >> output

    output.write(input.read(int(environ.get('CONTENT_LENGTH', '0'))))

    return [output.getvalue()]
Run Code Online (Sandbox Code Playgroud)

在输出中,PID值应始终相同.wsgi.multiprocess标志应为False.mod_wsgi.process_group值应该是您调用守护程序进程组的值.mod_wsgi.application_group应该是一个空字符串.

如果这不是您所看到的,请确保在进行配置更改后实际重新启动Apache.还添加:

LogLevel debug
Run Code Online (Sandbox Code Playgroud)

到VirtualHost的Apache配置.这样做会导致mod_wsgi在Apache错误日志中记录有关进程创建和脚本加载的更多消息,包括进程组和应用程序组正在发生的事情的详细信息.

有关调试的其他信息,请参阅:

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

如果仍有问题,建议您访问Google网上论坛的mod_wsgi邮件列表.