オープンソースライブラリを使用してウェブサーバーに接続しています。ウェブサーバーが極端に遅くなるのではないかと心配して、Rubyで簡単なテストをしてみたところ、これらの結果を得ました
Rubyプログラム:10個のHTTP GETで2.11秒
Rubyプログラム:100 HTTP GETで18.13秒
C#ライブラリ:10 HTTP GETで20.81秒
C#ライブラリ:100 HTTP GETの場合は36847.46秒
プロファイルを作成したところ、問題はこの関数であることがわかりました。
private HttpWebResponse GetRawResponse(HttpWebRequest request) {
HttpWebResponse raw = null;
try {
raw = (HttpWebResponse)request.GetResponse(); //This line!
}
catch (WebException ex) {
if (ex.Response is HttpWebResponse) {
raw = ex.Response as HttpWebResponse;
}
}
return raw;
}
マークされた行が完了するまでに1秒以上かかりますが、1つのリクエストを行うRubyプログラムは0.3秒かかります。これらのテストはすべて127.0.0.1で行っているため、ネットワーク帯域幅は問題ない。
この大きなスローダウンの原因は何ですか?
[〜#〜] update [〜#〜]
変更されたベンチマーク結果を確認してください。 100ではなく10のGETで実際にテストし、結果を更新しました。
遅いWebリクエストの主な原因は、プロキシプロパティです。 GetResponseメソッドを呼び出す前にこのプロパティをnullに設定すると、クエリはプロキシ自動検出ステップをスキップします。
request.Proxy = null;
using (var response = (HttpWebResponse)request.GetResponse())
{
}
プロキシの自動検出は、応答を返す前にクエリするのに最大7秒かかりました。このプロパティがHttpWebRequestオブジェクトに対してデフォルトで設定されているのは少し面倒です。
一度に複数の接続を開いているという事実に関係している可能性があります。デフォルトでは、開いているHTTP接続の最大量は2に設定されています。これを.configファイルに追加してみて、役立つかどうかを確認してください。
<system.net>
.......
<connectionManagement>
<add address="*" maxconnection="20"/>
</connectionManagement>
</system.net>
VB.Net MVCプロジェクトでも同様の問題が発生していました。
ローカルでは、PC(Windows 7)ではページリクエストにヒットするのに1秒未満かかりましたが、サーバー(Windows Server 2008 R2)では各ページリクエストに20秒以上かかりました。
プロキシをnullに設定する組み合わせを試しました
System.Net.WebRequest.DefaultWebProxy = Nothing
request.Proxy = System.Net.WebRequest.DefaultWebProxy
追加して構成ファイルを変更する
<system.net>
.......
<connectionManagement>
<add address="*" maxconnection="20"/>
</connectionManagement>
</system.net>
それでも、サーバー上の遅いページリクエスト時間は短縮されませんでした。最終的に解決策は、サーバー自体のIEオプション)の“ Automatically detect settings”オプションのチェックを外すことでした。([ツール]-> [インターネットオプション]で[接続タブ。[LAN設定]ボタンを押します)
サーバーでこのブラウザオプションをオフにした直後、すべてのページ要求時間は20秒以上から1秒未満に短縮されました。
この領域でOPに似たスローダウンが観察され始めましたが、MaxConnectionsを増やすと少し良くなりました。
ServicePointManager.DefaultConnectionLimit = 4;
しかし、この数のWebRequestを構築した後、遅延が戻ってきました。
私の場合、問題はPOSTを呼び出していて、応答を気にしなかったので、それを拾い上げたり、何もしなかったということでした。残念なことに、WebRequestはタイムアウトしました。
修正は、応答を取得して閉じるだけでした。
WebRequest webRequest = WebRequest.Create(sURL);
webRequest.Method = "POST";
webRequest.ContentLength = byteDataGZ.Length;
webRequest.Proxy = null;
using (var requestStream = webRequest.GetRequestStream())
{
requestStream.WriteTimeout = 500;
requestStream.Write(byteDataGZ, 0, byteDataGZ.Length);
requestStream.Close();
}
// Get the response so that we don't leave this request hanging around
WebResponse response = webRequest.GetResponse();
response.Close();
localhost以外のコンピューターを使用し、次に WireShark を使用して、実際に何が起こっているかを確認します。
他の人が言ったように、それは多くのことができます。 TCPレベルで物事を見ると、明確な画像が得られるはずです。
この回避策にどの程度正確に到達したかはわかりませんが、まだ調査する時間がないので、皆さん次第です。パラメーターがあり、HTTPWebRequestオブジェクトをインスタンス化する前に、クラスのコンストラクターで次のように使用しました。
System.Net.ServicePointManager.Expect100Continue = false;
正確な理由はわかりませんが、今では私の呼び出しはかなり速く見えます。
私はこれが古いスレッドであることを知っていますが、HttpWebRequestが遅いため丸1日を失いました。住所のリクエストはすべて1分以上かかりました。
最終的に、問題はアンチウイルスファイアウォール(Eset)にありました。インタラクティブモードでファイアウォールを使用していますが、Esetが何らかの理由でオフになっています完全に。そのため、リクエストは永遠に続きました。 Esetをオンにするの後にリクエストを実行すると、プロンプトファイアウォールメッセージが表示され、確認後は1秒未満のリクエストの実行になります。
ここで説明したすべての解決策を試してみましたが、運は5分ほどかかりました。
問題:同じセッションと明らかに同じCookie(同じサーバーで行われたリクエスト)が必要だったため、Request.CookiesからCookieをWebRequest.CookieContainerに再作成しました。応答時間は約5分でした。
私の解決策:Cookie関連のコードをコメントアウト and bam!呼び出しには1秒もかかりませんでした。
私にとって問題は、LogMeIn Hamachiをインストールしたことでした。皮肉なことに、同じプログラムをリモートでデバッグしてから、この極端な遅延を示し始めました。
参考までに、Hamachiネットワークアダプターを無効にするだけでは十分ではありませんでした。Windowsサービスによってアダプターが再び有効になったようだからです。
また、Hamachiネットワークに再接続しても問題は解決しませんでした。アダプタを無効にする(LogMeIn Hamachi Windowsサービスを無効にする)か、おそらくHamachiをアンインストールするだけで、問題は解決しました。
HttpWebRequest
に特定のネットワークアダプターを経由するように依頼することはできますか?
これは私のために働いた:
<configuration>
<system.net>
<defaultProxy erabled="false"/>
</system.net>
</configuration>