次のシナリオがあります。
シングルユーザーリクエストでいくつかのサードパーティサーバーからのデータを集約するWebサービスがあります。サードパーティへのリクエストは、SOAPまたはXMLデータを含むプレーンなurllib2リクエストであり、それぞれが個別のスレッドで実行されます。
これが私がしていることの全体像です:
ThirdParty1(Thread):
def run(self):
try:
result = SOAPProxy('http://thirdparty.com', timeout=2).method(params)
dostuff_and_save(result) # save results on database
except Exception:
log.warn('Ooops')
ThirdParty2(Thread): ...
def myview(params):
thread = [ThirdParty1(), ThirdParty2()]
for t in thread: t.start()
for t in thread: t.join(timeout=2)
return result # this is actually just a token, that I use to retrieve the data saved by the threads
私の現在の問題は、サードパーティのサーバーのいずれかがユーザーの側にハングアップしたときに、ユーザーの要求に対する応答を確実に返すことです。スレッド結合、SOAPProxyオブジェクト、およびを実行するためにタイムアウトを設定しようとしましたsocket.setdefaulttimeout
。タイムアウトは考慮されません。
私はなんとかSOAPProxyの問題を掘り下げて、それがhttplibを使用し、httplibがsocket.makefile()を深く使用していることを発見しました。
socket.makefile([mode [、bufsize]])
ソケットに関連付けられているファイルオブジェクトを返します。(ファイルオブジェクトは[ファイル]> [オブジェクト]で説明されています。)ファイルオブジェクトはソケットファイル記述子のdup()pedバージョンを参照するため、>ファイルオブジェクトとソケットオブジェクトは個別に閉じたりガベージコレクションしたりできます。ソケットはブロッキングモードである必要があります(タイムアウトを設定することはできません)。オプションのmode引数とbufsize引数は、組み込みのfile()関数と同じように解釈されます。
私が見つけた他のすべてのSOAPライブラリは、いずれにせよ、httplibも使用しています。問題を複雑にするために、要求しているスレッドからデータベースにアクセスする必要があるかもしれませんが、この種の戦略でスレッドを強制終了した場合の結果を完全には理解していません。可能です。
次に、私の質問は次のとおりです。
タイムアウトが尊重されない場合、Webサービスはどのようにしてユーザーに期限内に応答し、動作の悪いサードパーティサーバーを適切に処理できますか?
HTTPResponseがmakefileを使用するという事実は、私が思っていたほど悪くはないかもしれませんが、デフォルトでmakefile
は実際には非バッファリングであり、タイムアウト例外が発生する可能性があります。これが私が試したことです。
あるコンソールで開いnetcat -l -p 8181 '0.0.0.0'
て、別のコンソールで開いてpython2.7
実行しました。
>>> import socket
>>> af, socktype, proto, canoname, sa = socket.getaddrinfo('0.0.0.0', 8181, 0, socket.SOCK_STREAM)[0]
>>> s=socket.socket(af, socktype, proto)
>>> s.settimeout(.5)
>>> s.connect(sa)
>>> f=s.makefile('rb', 0)
>>> f.readline()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/socket.py", line 430, in readline
data = recv(1)
socket.timeout: timed out
しかし、信頼できるサードパーティの要求を行う方法に関する私の問題は解決していません。