【问题标题】:Multithreading problems with xmlrpclib.ServerProxy under python 2.7python 2.7下xmlrpclib.ServerProxy的多线程问题
【发布时间】:2014-08-27 08:21:20
【问题描述】:

我有一个应用程序将xmlrpclib.ServerProxy 实例化一次,然后将其传递给多个线程(Web 应用程序请求),它们都同时执行 XML/RPC 调用。这适用于 python 2.6。在 python 2.7 中,一旦我们处于多线程环境中,就会遇到很多错误(ResponseNotReadyCannotSendRequest)。

# 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 对象?

【问题讨论】:

    标签: python multithreading python-2.7 xml-rpc xmlrpclib


    【解决方案1】:

    我们找到了问题的原因:在 python 2.6 中,每个 XML/RPC 方法调用都会创建一个 TCP 连接。另一方面,Python 2.7 为每个 ServerProxy 对象打开一个 TCP 连接,并使其保持打开状态(使用支持 keep-alive 的服务器)。此外,该类不是线程安全的,因此并发请求可能会相互干扰。

    显然,2.6 版本隐含地是线程安全的,因为 TCP 连接不会被重用,并且所有特定于连接的数据似乎都保存在非共享堆栈变量中。

    所以可能的解决方案是:

    1. 为每个线程创建一个ServerProxy 对象(并隐式打开一个 TCP 连接)
    2. 锁定对单个共享 ServerProxy 对象的访问权限
    3. 实现请求队列

    【讨论】:

    • 是否有解决方案 2 和/或 3 的食谱?我面临同样的问题,但不确定我应该如何实现它。如果以前做过(谷歌没有帮助),我就不必重新发明轮子了。
    【解决方案2】:

    大多数代码都不是线程安全的。但是我不知道为什么代码可以在 2.6 中工作,但在 2.7 中会引发错误。

    这是对这个问题的另一种看法:

    • 使用更高级别的threading 模块

    • 代理是每个线程的,而不是全局的。这样更安全,因此线程不会因为覆盖共享的全局对象而相互混淆。

    • 线程最后明确join()ed,以确保它们全部完成

    来源

    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()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-08-09
      • 2016-07-10
      • 1970-01-01
      • 1970-01-01
      • 2013-11-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多