SocketServer.ThreadingMixinを使用するSimpleXMLRPCServersのチェーンを使用しているときに、httplib.CannotSendRequest例外を断続的に受信しています。Python:スレッドのSimpleXMLRPCServersをネストするときのhttplib.CannotSendRequest
は私がのSimpleXMLRPCServerの関数を呼び出すためにxmlrpclibを使用するクライアントスクリプトを持っている:私は「連鎖」によって何を意味
は次のとおりです。そのサーバーは次に、別のSimpleXMLRPCServerを呼び出します。私が聞こえることどのように複雑な実現が、このアーキテクチャが選択されていることは良い理由がある、と私はそれが可能であってはならない理由が表示されません。
(testclient)client_script ---calls-->
(middleserver)SimpleXMLRPCServer ---calls--->
(finalserver)SimpleXMLRPCServer --- does something
- 私はSocketServer.ThreadingMixinを使用していない場合、この問題は発生しません(私はこれで解決しないように要求がマルチスレッドにする必要があります。)
- 私が唯一持っている場合単一のレベルのサービス(つまり、クライアントスクリプトが最終サーバーを直接呼び出している)は発生しません。
私は、以下の簡単なテストコードで問題を再現することができました。 3つのスニペットがあります
finalserver:
import SocketServer
import time
from SimpleXMLRPCServer import SimpleXMLRPCServer
from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler
class AsyncXMLRPCServer(SocketServer.ThreadingMixIn,SimpleXMLRPCServer): pass
# Create server
server = AsyncXMLRPCServer(('', 9999), SimpleXMLRPCRequestHandler)
server.register_introspection_functions()
def waste_time():
time.sleep(10)
return True
server.register_function(waste_time, 'waste_time')
server.serve_forever()
middleserver:
import SocketServer
from SimpleXMLRPCServer import SimpleXMLRPCServer
from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler
import xmlrpclib
class AsyncXMLRPCServer(SocketServer.ThreadingMixIn,SimpleXMLRPCServer): pass
# Create server
server = AsyncXMLRPCServer(('', 8888), SimpleXMLRPCRequestHandler)
server.register_introspection_functions()
s = xmlrpclib.ServerProxy('http://localhost:9999')
def call_waste():
s.waste_time()
return True
server.register_function(call_waste, 'call_waste')
server.serve_forever()
testclient:
import xmlrpclib
s = xmlrpclib.ServerProxy('http://localhost:8888')
print s.call_waste()
再現するために、次の手順を使用する必要があります。
- 実行Pythonのfinalserver.py
- が実行Pythonのmiddleserver.py
- 実行Pythonのtestclient.py
- (3)は、まだかなりのPython testclient.py
の別のインスタンスを実行し、実行している間頻繁に(ほぼすべての時間)あなたは、あなたがすぐに(4)再びエラーが発生しませんステップを実行しようとした場合、興味深いことに、手順4を実行しようとする最初の時間の下にエラーが発生します。
Traceback (most recent call last):
File "testclient.py", line 6, in <module>
print s.call_waste()
File "/usr/lib64/python2.7/xmlrpclib.py", line 1224, in __call__
return self.__send(self.__name, args)
File "/usr/lib64/python2.7/xmlrpclib.py", line 1578, in __request
verbose=self.__verbose
File "/usr/lib64/python2.7/xmlrpclib.py", line 1264, in request
return self.single_request(host, handler, request_body, verbose)
File "/usr/lib64/python2.7/xmlrpclib.py", line 1297, in single_request
return self.parse_response(response)
File "/usr/lib64/python2.7/xmlrpclib.py", line 1473, in parse_response
return u.close()
File "/usr/lib64/python2.7/xmlrpclib.py", line 793, in close
raise Fault(**self._stack[0])
xmlrpclib.Fault: <Fault 1: "<class 'httplib.CannotSendRequest'>:">
インターネットは、この例外はのGetResponseコールを介在せずにhttplib.HTTPConnection.requestへの複数の呼び出しが原因で発生することができると言うように見えます。しかしながら、インターネットはSimpleXMLRPCServerの文脈でこれを議論しません。 httplib.CannotSendRequestの問題を解決する方向にあるあらゆるポインタが評価されます。
============================================== ============================================= ANSWER:
さて、私は少し愚かです。私は、時間が長すぎてコードを見ていたと思うので、答えが実際の質問に載っているので、顔をして私を見つめている明白な解決策を見逃してしまったと思う。
基本的にCannotSendRequestが発生する介入する「要求」操作によってhttplib.HTTPConnectionが中断されたとき。各httplib.HTTPConnection.requestは、.getresponse()呼び出しとペアにする必要があります。そのペアリングが別の要求操作によって中断された場合、2番目の要求はCannotSendRequestエラーを生成します。 so:getresponseが呼び出される前に同じ接続で2つのリクエストがあるため、失敗します。私の質問にそれをバックリンク
:
- このような接続が行われている三つのプログラムで唯一の場所はServerProxyは呼び出しです。
- 問題はスレッド化中にのみ発生するため、競合状態になる可能性があります。 ServerProxyはコールが共有されている唯一の場所がmiddleserver.py
である
import SocketServer
from SimpleXMLRPCServer import SimpleXMLRPCServer
from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler
import xmlrpclib
class AsyncXMLRPCServer(SocketServer.ThreadingMixIn,SimpleXMLRPCServer): pass
# Create server
server = AsyncXMLRPCServer(('', 8888), SimpleXMLRPCRequestHandler)
server.register_introspection_functions()
def call_waste():
# Each call to this function creates its own serverproxy.
# If this function is called by concurrent threads, each thread
# will safely have its own serverproxy.
s = xmlrpclib.ServerProxy('http://localhost:9999')
s.waste_time()
return True
server.register_function(call_waste, 'call_waste')
server.serve_forever()
、同じインスタンスの危険ServerProxyはのがHTTPConnection.request複数を呼び出すは存在しません連続して1回以上。プログラムは意図したとおりに動作します。
申し訳ありません。