我有一个应用程序,它实例化一次xmlrpclib.ServerProxy
,然后将其传递给多个线程(Web应用程序请求),这些线程同时执行XML / RPC调用。这适用于python 2.6。使用python 2.7,我们在多线程环境中遇到很多错误(ResponseNotReady
,CannotSendRequest
)。
# This code works well in python 2.6, and breaks in python 2.7.
import xmlrpclib
import thread
proxy = xmlrpclib.ServerProxy("http://localhost:5000/")
def fetch_users():
print proxy.getUsers()
for _ in range(10):
thread.start_new_thread(fetch_users, ())
while(1):
pass
这里有什么问题,是否有一种重新使用ServerProxy对象的线程安全方式?
答案 0 :(得分:5)
我们找到了问题的原因:在python 2.6中,在每个XML / RPC方法调用上都创建了一个TCP连接。另一方面,Python 2.7为每个ServerProxy对象打开一个TCP连接,并使其保持打开状态(使用支持keep-alive
的服务器)。此外,该类不是线程安全的,因此并发请求可能会相互干扰。
显然,2.6版本是隐含线程安全的,因为TCP连接不会被重用,并且所有特定于连接的数据似乎都保存在非共享堆栈变量中。
所以可能的解决方案是:
ServerProxy
对象(并隐含地打开TCP连接)ServerProxy
对象答案 1 :(得分:0)
大多数代码都不是线程安全的。但是我不知道为什么代码在2.6中有用,但在2.7中引发错误。
这是对问题的另一种看法:
使用更高级别的threading
模块
代理是每线程,而不是全局。这样更安全,因此线程不会通过覆盖共享的全局对象而相互混淆。
线程最后明确join()
,以确保它们全部完成
import xmlrpclib
import threading
def fetch_users():
proxy = xmlrpclib.ServerProxy("http://localhost:5000/")
print proxy.getUsers()
for _ in range(10):
threading.Thread(target=fetch_users, args=()).start()
# wait for all threads to exit
for th in threading.enumerate():
th.join()