我目前正在熟悉 Python 中 Web 应用程序的 WSGI 规范。我设置 Apache(使用 mod-wsgi)来调用一个小应用程序,该应用程序当前只显示线程 ID 号,以尝试观察每个请求的唯一性:
import thread
def application(environ, start_response)
start_response('200 Ok', [('Content-type', 'text/plain')])
output = "current thread id: %s" % thread.get_ident()
return [output]
我很快注意到,过了一会儿,后续请求会重用相同的线程。
如果我的理解是正确的,为了让我的应用程序具有“特定于上下文”的变量,我需要使用类似于以下的方案来存储它们:
lock = thread.allocate_lock()
lock.acquire()
thread_id = get_ident()
threadsafe[thread_id]['user'] = request.username
lock.release()
然后我可以以类似的方式从应用程序的不同部分访问它们。在这种情况下,我唯一的保证是该值属于该特定线程。然而,使用同一个线程的请求可能仍然会踩到对方的脚趾(例如,请求访问来自先前请求的剩余值)。我的结论是,要以真正独特的方式处理每个请求,除了“thread_id”之外,我还需要另一个键来区分使用同一线程的请求。
使用 uuid 之类的唯一键,我可以做到这一点
lock.acquire()
uuid = uuid.uuid4()
thread_id = get_ident()
threadsafe[(thread_id, uuid)]['user'] = request.username
lock.release()
但这意味着我也有办法以线程安全的方式检索 uuid 值,就像我以后可以检索 thread_id 一样。
我得出了正确的结论吗?如果是这样,我如何获得该附加密钥?
编辑
我突然想到我的问题是错误的二分法。我以线程可以与自身同时运行的观点来处理事情,而实际上这是不可能的。使用同一线程的请求必须串行运行。因此,我实际上可以使用 uuid 来避免使用线程的陈旧值,但只有在将其存储为线程保存值本身之后。
# somewhere early in the request
threadsafe[thread_id]['current_uuid'] = uuid.uuid4()
# later
lock.acquire()
thread_id = get_ident()
uuid = threadsafe[thread_id]['current_uuid']
threadsafe[(thread_id, uuid)]['user'] = request.username
lock.release()