応答時間が突然急上昇するのはなぜですか?


12

IISでホストされているServiceStackを使用して実装されたAPIがあります。APIの負荷テストの実行中に、応答時間は良好であるが、サーバーあたり約3,500人の同時ユーザーに到達するとすぐに応答時間が急速に低下することがわかりました。2台のサーバーがあり、7,000人のユーザーでサーバーにアクセスすると、すべてのエンドポイントで平均応答時間が500ミリ秒未満になります。ボックスはロードバランサーの背後にあるため、サーバーごとに3,500の同時実行が可能です。ただし、同時ユーザーの合計数を増やすとすぐに、応答時間が大幅に増加します。同時ユーザーをサーバーごとに5,000に増やすと、エンドポイントあたりの平均応答時間は約7秒になります。

サーバーのメモリとCPUは非常に低く、応答時間は良好ですが、劣化した後も同様です。10,000人の同時ユーザーのピーク時には、CPUの平均は50%をわずかに下回り、RAMは16のうち約3〜4 GBになります。以下のスクリーンショットは、合計10,000人の同時ユーザーによる負荷テスト中のperfmonのいくつかの主要なカウンターを示しています。強調表示されているカウンターは要求/秒です。スクリーンショットの右側では、1秒あたりのリクエスト数のグラフが非常に不安定になっていることがわかります。これは、応答時間が遅い場合の主な指標です。このパターンを見るとすぐに、負荷テストで応答時間が遅いことに気付きます。

1秒あたりのリクエストが強調表示されたperfmonスクリーンショット

このパフォーマンスの問題をトラブルシューティングするにはどうすればよいですか?これがコーディングの問題か構成の問題かを特定しようとしています。この動作を説明できるweb.configまたはIISの設定はありますか?アプリケーションプールは.NET v4.0を実行しており、IISバージョンは7.5です。デフォルト設定から行った唯一の変更は、アプリケーションプールのキューの長さの値を1,000から5,000 に更新することです。また、次の構成設定をAspnet.configファイルに追加しました。

<system.web>
    <applicationPool 
        maxConcurrentRequestsPerCPU="5000"
        maxConcurrentThreadsPerCPU="0" 
        requestQueueLimit="5000" />
</system.web>

詳細:

APIの目的は、さまざまな外部ソースからのデータを組み合わせてJSONとして返すことです。現在、InMemoryキャッシュの実装を使用して、データレイヤーで個々の外部呼び出しをキャッシュしています。リソースへの最初の要求は、必要なすべてのデータをフェッチし、同じリソースに対する後続の要求はキャッシュから結果を取得します。特定の設定間隔でキャッシュ内の情報を更新するバックグラウンドプロセスとして実装される「キャッシュランナー」があります。外部リソースからデータを取得するコードの周りにロックを追加しました。また、エンドポイントが最も遅い外部呼び出しと同じくらい遅くなるように非同期の方法で外部ソースからデータをフェッチするサービスを実装しました(もちろんキャッシュにデータがある場合を除きます)。これは、System.Threading.Tasks.Taskクラスを使用して行われます。プロセスで使用できるスレッドの数の点で制限にぶつかりますか?


5
CPUにはいくつのコアがありますか?おそらく、1つのコアを最大限に活用しているのでしょう。マジックナンバーが50%、25%、または12.5%の場合、コアを最大にしたため、何らかの理由でアイドル状態の他のコアを使用できないことを示しています。最大コアをチェックしてください。
デビッドシュワルツ

1
リクエストごとに1つのスレッドを取得しましたか?5000件のリクエストに対して5000個のスレッドがありますか?そうする場合、それはおそらくあなたの問題です。代わりに、スレッドプールを作成し、スレッドプールを使用して要求を処理し、要求がスレッドプールに入ってくるとキューに入れる必要があります。スレッドがリクエストを終了すると、キューからリクエストを処理できます。この種の議論は、スタックオーバーフローに最適です。スレッドが多すぎると、コンテキストスイッチが多すぎます。
マット

1
ここでの健全性チェックだけで、すべてのバックグラウンドプロセスをオフにして、JSONがキャッシュから静的データを返す場合の動作を確認しましたか?つまり、JSONに静的データを要求させ、キャッシュを完全に更新する「外部非同期呼び出し」を削除します。また、すべてのリクエストで処理されるJSONデータの量に応じて、ネットワークのスループットと、サーバーがデータを十分に速くプッシュできないためにリクエストがバックアップを開始するかどうかを検討しましたか?
ロバート

1
上記のデイビッドの提案に+1。テストを本当にやり直し、各コアの使用率を注意深く確認する必要があります。他に何もなければ、できるだけ早くこれを行うことをお勧めします。第二に、私はあなたのキャッシュを少し疑っています。ロックの競合は、まさにこのような動作を示します。一部のクリティカルポイントでは、ロックにより遅延が発生し、ロックが通常よりも長く保持され、物事が急速に下降する転換点が生じます。キャッシュコードとロックコードを共有できますか?
スティーブクック

1
サーバーのディスクセットアップはどのようなものですか(サーバーは負荷分散されているため、ディスクセットアップは同じであると仮定しています)。最初の投稿でドライブ/サーバーのすべての仕様を投稿できますか?IISおよびIISログファイルが存在する物理ドライブのディスクにperfmonを投げましたか?3,500リクエスト= 3,500+ IISログ全体でディスクに問題が発生している可能性があります。それらが同じディスク/パーティションにある場合、大きな問題が発生する可能性があります。
専門的ジョー・

回答:


2

@DavidSchwartzと@Mattに続いて、これはスレッドのように見え、管理の問題をロックします。

私は提案します:

  1. 外部呼び出しとそれらのために生成されたキャッシュをフリーズし、静的外部情報を使用して負荷テストを実行します。これは、サーバー-環境側に関連しない問題を破棄するためです。

  2. スレッドプールを使用しない場合は使用します。

  3. あなたが言った外部呼び出しについて「非同期ソースでデータを取得するサービスも実装しました。これにより、エンドポイントが最も遅い外部呼び出しと同じくらい遅くなるはずです(もちろんキャッシュにデータがある場合を除きます)。 」

質問は次のとおりです。-外部呼び出し中にキャッシュデータがロックされていないか、または外部呼び出し結果をキャッシュに書き込むときにのみロックされているかどうかを確認しましたか。(あまりにも明らかですが、言う必要があります)。-キャッシュ全体をロックしますか、それとも一部をロックしますか?(あまりにも明らかですが、言う必要があります)。-非同期であっても、外部呼び出しはどのくらいの頻度で実行されますか?あまり頻繁に実行されなくても、キャッシュがロックされている間にユーザー呼び出しからキャッシュへの過剰なリクエストによってブロックされる可能性があります。多くのスレッドが一定の間隔で待機しており、「ロック」も管理する必要があるため、このシナリオでは通常、使用されるCPUの割合が固定されています。-外部タスクが遅いシナリオの到着時に応答時間も長くなることを意味するかどうかを確認しましたか?

それでも問題が解決しない場合は、Taskクラスを回避し、ユーザー要求を管理する同じスレッドプールを介して外部呼び出しを行うことをお勧めします。これは、前のシナリオを回避するためです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.