次の方法で共有


HttpWebRequestのタイムアウトに関して

質問

2012年11月6日火曜日 7:21

HttpWebRequestのオブジェクトを作成し、HTTPリクエストを行う処理中に
次のような例外が発生していることが分かりました。

*******************************************************************
System.Net.WebException: 操作はタイムアウトになりました。
   場所 System.Net.HttpWebRequest.GetRequestStream()
*******************************************************************

この例外がいったん発生してからは、該当サービスの再起動を行うまで
同じ例外が発生し続けました。

原因として、HttpWebRequestインスタンスを確実にAbortしておらず、
HttpWebRequestの"何かが"残り、WebStreamの読み書きができず
HttpWebRequestが固まることがあるらしい
(この固まる現象はHttpWebRequestを連続で呼び出すときに発生しやすい)。

その結果、読み書きができずタイムアウトが発生するところまではわかりましたが、再現方法が分かりません。
おそらくこのタイムアウトはReadWriteTimeoutであろうと推測しています。

実験として
同じDLL内の該当メソッドをほぼ同時に50プロセスで10回繰り返して実行しましたが、
現象を再現することができませんでした。

発生した環境は
・WindowsServer2008
です。

言語はC#(3.5)です。

同様の現象にあたったことがある方がいらっしゃいましたら、

そのときの原因、解決方法、再現方法などを教えていただけないでしょうか。

よろしくお願いします。

すべての返信 (2)

2012年11月6日火曜日 8:12

回答ではありませんが、

HttpWebRequestクラスは直接TCPコネクションを処理しているわけではありません。ServicePointManagerクラスによって管理されているServicePointクラスを介して通信してます。(更にその先にConnectionGroupやらConnectionクラスがありますが。)
そのため、もしも通信できないTCPコネクションを持ったServicePointインスタンスが生き続け、HttpWebRequestがそのServicePointばかりを割り当てられた場合、質問の現象のようにエラーになり続けます。

通常はエラーを検出した時点でそのTCPコネクションを破棄するはずですが…。再現方法はわかりません。トレースログを取得すれば、現象再現時に原因もわかるでしょうし、そこから対策を立てられるとは思いますが。

ちなみにHttpWebRequestの接続先はどちらでしょうか? あまりに頻繁に接続をするとDoS攻撃と判断され、相手側(Webサーバー自身や途中のルーターなど)が応答しなくなる場合もあります。その場合、HttpWebRequestからすればタイムアウトが発生したように検出されるかもしれません。(接続エラーかもしれませんが)


2012年11月7日水曜日 3:21

ServicePointクラスのご指摘ありがとうございました。

>ちなみにHttpWebRequestの接続先はどちらでしょうか?
接続先は、業務用情報をやりとりするためのAPIです。
接続先がメンテナンス中のさいに発生しました。

メンテナンス開始
↓ この間接続できず※
メンテナンス終了
↓ メンテ終了後も、接続できず
こちらのサービス再起動で復帰

※の期間は、最初は404エラーが発生しており、リトライをしている最中に
今回話題にしました、"操作はタイムアウトになりました。"エラーが発生しました。
メンテ終了後も、"操作はタイムアウトになりました。"エラーが発生し続けました。

ですので、破棄されていないServicePointインスタンスを使用し続けているのが原因かもしれません。

HttpWebRequest作成時に、都度都度ServicePointインスタンスを作成しているように
実装しているつもりですが、調査してみます。

DoS攻撃と判断されたかどうかは不明ですので、
回答の望みは薄いですが、サイト側に聞いてみます。