4

您能否在多个 WSGI 线程/进程之间共享一个对象(并且以在 *NIX 和 Windows 上都可以工作的方式)?

基本前提:(1)我有一个将连接到后端服务器的 WSGI 前端。我有一个序列化类,其中包含有关如何序列化/反序列化各种对象的规则,包括特定于该项目的类。因此,它需要一些设置来告诉它如何处理自定义对象。然而,它是无状态的——多个线程可以同时访问它以毫无问题地序列化它们的数据。(2) 有socket可以连接到后端。我宁愿有一个套接字池而不是每次有连接时都创建/销毁。

注意:我不介意有多个 (1) 和 (2) 实例的解决方案,但理想情况下,我希望它们尽可能少地创建/初始化。我不确定内部结构,但是如果线程循环而不是关闭并让服务器在新请求上重新打开,那么每个线程有一个数据集就可以了(因此,套接字和序列化程序每次初始化一次)线程,但重复使用它处理的每个后续调用。)实际上每个线程有一个套接字,如果它是这样工作的,那将是最好的,因为我不需要套接字池并且必须处理互斥锁。

注意:这不是会话,与会话无关。这不应该关心谁在调用服务器。它只是在线程创建速度较慢或内存很大但 CPU 相对较慢的系统上调整性能。

编辑 2:下面的代码将提供一些关于您的系统如何共享变量的信息。您需要多次加载该页面才能获得一些诊断信息...

from datetime import *;
from threading import *;
import thread;
from cgi import escape;
from os import getpid;

count = 0;
responses = [];
lock = RLock();

start_ident = "%08X::%08X" % (thread.get_ident(), getpid());

show_env = False;

def application(environ, start_response):
    status = '200 OK';
    this_ident = "%08X::%08X" % (thread.get_ident(), getpid());


    lock.acquire();
    current_response = """<HR>
<B>Request Number</B>: """ + str(count) + """<BR>
<B>Request Time</B>: """ + str(datetime.now()) + """<BR>
<B>Current Thread</B>: """ + this_ident  + """<BR>
<B>Initializing Thread</B>: """ + start_ident  + """<BR>
Multithread/Multiprocess: """ + str(environ["wsgi.multithread"]) + "/" + str(environ["wsgi.multiprocess"]) +"""<BR>
"""
    global count;
    count += 1;

    global responses;
    responses.append(current_response)
    if(len(responses) >= 100):
        responses = responses[1:];
    lock.release();

    output="<HTML><BODY>";

    if(show_env):
        output+="<H2>Environment</H2><TABLE><TR><TD>Key</TD><TD>Value</TD></TR>";
        for k in environ.keys():
            output += "<TR><TD>"+escape(k)+"</TD><TD>"+escape(str(environ[k]))+"</TD></TR>";
        output+="</TABLE>";
    output += "<H2>Response History</H2>";
    for r in responses:
        output += r;
    output+="</BODY></HTML>"


    response_headers = [('Content-type', 'text/html'),
                        ('Content-Length', str(len(output)))]
    start_response(status, response_headers)
    return [output]
4

2 回答 2

2

通过我对http://code.google.com/p/modwsgi/wiki/ProcessesAndThreading的阅读,如果您启用了多处理和多线程(与工作者一样,或者如果您有

WSGIDaemonProcess 示例进程=2 线程=25

那么你有两个问题:多个线程意味着你可以共享一个变量,但它只能2 个进程中的每个进程中共享。除非您明确地让另一个守护程序(NON-APACHE)处理消息传递和请求,否则没有真正的方法可以在进程之间共享变量。

假设您对数据库连接池有一个简单的需求。使用上述配置,您将拥有两个池,每个池服务 25 个线程。这对大多数人来说都很好,因为线程是轻量级的,而进程不是(据说)。

那么,如何实现呢?

  • 在您的一个模块中,创建一个实例化连接池的变量。让每个线程(实际上是为单个请求提供服务的代码)在适当的时间获得连接使用它,并将其返回到池中。不要忘记最后一部分,你会很快用完连接。

  • 创建另一个守护进程(与 Apache 无关)。实例化一个共享内存数组。将包含 db 连接和进程 ID 的对象放入此数组中(以 null 开始)。在 while-True 循环中,侦听套接字上的连接,当你得到一个连接时,生成一个子进程,传入共享数组,数组元素的数量。子进程填写它知道的进程ID,它处理请求,关闭任何游标,然后删除它的进程ID并退出。

  • 聘请熟悉 WSGI 和 db 连接池的程序员为您做这件事;-)。

于 2013-09-11T20:46:14.250 回答
2

有关 mod_wsgi 进程/线程模型如何工作的一些阅读,请参阅:

请特别注意有关构建可移植应用程序的部分。

无论您使用什么 WSGI 服务器,那里的评论并没有什么不同。所有 WSGI 服务器也属于多进程/单进程、多线程/单线程类别之一。

于 2013-04-17T11:26:19.377 回答