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秒あたりのリクエスト数のグラフが非常に不安定になっていることがわかります。これがメインです応答時間が遅いことを示すインジケーターこのパターンが表示されるとすぐに、負荷テストで応答時間が遅いことがわかります。
このパフォーマンスの問題のトラブルシューティングはどのように行うのですか?これがコーディングの問題か構成の問題かを特定しようとしています。 web.configまたはIISこの動作を説明する可能性のある設定はありますか?アプリケーションプールは.NET v4.0およびIISバージョンは7.5です。デフォルト設定から行った唯一の変更は、アプリケーションプールQueue Lengthの値を1,000から5,000に更新することです。 Aspnet.configファイルに次の構成設定も追加しました。
<system.web>
<applicationPool
maxConcurrentRequestsPerCPU="5000"
maxConcurrentThreadsPerCPU="0"
requestQueueLimit="5000" />
</system.web>
詳細:
APIの目的は、さまざまな外部ソースからのデータを組み合わせ、JSONとして返すことです。現在、InMemoryキャッシュ実装を使用して、データレイヤーで個々の外部呼び出しをキャッシュしています。リソースへの最初のリクエストは必要なすべてのデータをフェッチし、同じリソースに対する後続のリクエストはキャッシュから結果を取得します。キャッシュ内の情報を一定の間隔で更新するバックグラウンドプロセスとして実装された「キャッシュランナー」があります。外部リソースからデータをフェッチするコードにロックを追加しました。また、エンドポイントが最も遅い外部呼び出しと同じくらい遅くなるように、非同期の方法で外部ソースからデータをフェッチするサービスも実装しました(もちろん、キャッシュにデータがない限り)。これは、System.Threading.Tasks.Taskクラスを使用して行われます。 プロセスで使用可能なスレッドの数の点で制限に達していませんか?
@DavidSchwartzと@Mattに続いて、これはスレッドのように見え、問題の管理をロックします。
私は提案します:
外部呼び出しとそれらに対して生成されたキャッシュをフリーズし、静的外部情報を使用して負荷テストを実行し、サーバーに関連しない問題を破棄します-環境側。
使用しない場合は、スレッドプールを使用します。
外部呼び出しについて、「外部ソースからデータを非同期にフェッチするサービスも実装したため、エンドポイントが最も遅い外部呼び出しと同じくらい遅くなるはずです(もちろん、キャッシュにデータがない場合)。 」
質問は次のとおりです。-外部呼び出し中にキャッシュデータがロックされているか、または外部呼び出し結果をキャッシュに書き込むときにのみロックされているかどうかを確認しましたか。 (あまりにも明白ですが、言わなければなりません)。 -キャッシュ全体またはその一部をロックしますか? (あまりにも明白ですが、言わなければなりません)。 -それらが非同期であっても、外部呼び出しはどのくらいの頻度で実行されますか?それほど頻繁に実行されない場合でも、キャッシュがロックされているときに、ユーザー呼び出しからのキャッシュへの過剰な要求によってブロックされる可能性があります。多くのスレッドが固定間隔で待機しており、「ロック」も管理する必要があるため、このシナリオは通常、使用されているCPUの固定割合を示しています。 -遅いシナリオが到着したときに、外部タスクが応答時間も増加することを意味するかどうかを確認しましたか?
それでも問題が解決しない場合は、タスククラスを回避し、ユーザーの要求を管理するのと同じスレッドプールを介して外部呼び出しを行うことをお勧めします。これは、前のシナリオを回避するためです。