2013-04-17 196 views
3

你能已在多个WSGI线程/进程间共享的对象(和方式,将在两个工作* NIX和Windows)?共享变量

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

注:我不介意那里有(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] 

回答

2

有关进程/线程模型的工作原理的mod_wsgi看到一些阅读:

特别注意构建便携式应用程序的部分。

的意见有没有真的有什么不同,无论你用什么WSGI服务器。所有WSGI服务器也属于这些多进程/单进程,多线程/单线程类别之一。

+0

谢谢,我看到了,但不知道如何应用它。基本上:if(wsgi.multithread == True) - 同一进程中的其他执行将共享相同的变量,而这些变量不是函数范围的。如果(wsgi.multiprocess == True),那么它们将共享相同的变量,这些变量不是函数范围的。假设我在ThreadID 59926中完成请求。 ThreadID 59926可能会得到一些后续请求,并且与59926具有相同的全局变量? –

+0

如果wsgi.multiprocess == True,那么线程访问的全局变量可能与线程可能在完全不同的进程中运行的相同。谈论多进程时,你是不是指“他们不会分享”? –

+0

我不知道他们什么时候会分享。我想如果它是多进程的,他们会共享以节省资源(不是一个难以实现的效果)。我做了一个很好的小演示,我将添加到我原来的帖子。 –

2

通过我的http://code.google.com/p/modwsgi/wiki/ProcessesAndThreading阅读,如果你有多重和多线程的(如工人,或者如果你有

WSGIDaemonProcess例如流程= 2个线程= 25

那么你有两个问题:多个线程意味着你可以共享一个变量,但它只会共享内各2个进程的。还有就是进程之间共享瓦尔除非你明确地有另外一个守护进程(NON-APACHE)处理的消息传递和要求没有真正的方法。

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

那么,如何实现呢?

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

  • 创建另一个守护进程(与Apache不相关)。实例化一个共享内存数组。在这个数组中放入由db连接和一个进程Id组成的对象(null开始)。在while循环中,监听套接字上的连接,当你得到一个连接时,产生一个子进程,传入共享数组,数组元素的数量。子进程填充它知道的进程ID,它处理请求,关闭所有游标,然后删除它的进程ID并退出。

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