問題点

カスタムアプリケーションの多くは AEM から Web サービスを呼び出します。  これらのアプリケーションは Apache Commons HTTP Client あるいは、その他のライブラリを使用します。  バックエンドシステムにパフォーマンス上の問題が発生すると、AEM の応答時間が遅くなります。  さらに、ハングしているスレッドが多すぎると、JVM ガベージコレクションの遅延、メモリ不足によるエラー、OS スレッドの消費などの原因になります。

スレッドダンプまたはヒープダンプを AEM からキャプチャすると、Web サービスの呼び出しで待機している多数のスレッドが表示されます。

シナリオ例
:[1] の下に表示されているのは、JVM スレッドダンプからのスタックトレースの例です。  これは、バックエンドサービスが正常に実行されていないアプリケーションがある AEM インスタンスよりキャプチャされました。

スレッドダンプによっていくつかの問題が示されています。

  • 次のリクエストスレッドは、応答しなかった Web サービス上で待機中のままです。  ソケットの読み取りタイムアウトが設定されいなかったため、スレッドは永久に待機中のままでした。そのソリューションにおいてはここを参照します。
  • 1つのリクエストスレッドで数百件ものスレッドが待機していました。これは、スレッドプールが1つのスレッドに設定され、最初にキューに入れられ、最初に除去されたからです。保留中のスレッド数が多くなると、メモリ使用率が高くなります。ソリューションはここを参照します。
  • 呼び出された Web サービスが、応答に時間がかかりすぎています。  これにより、既存スレッドが蓄積されました。

ハイライト表示されたスタックの行に留意してください。

  • 黄色では、カスタムアプリケーションが Spring Framework の RestTemplate ライブラリを使用して Web サービスの呼び出しを行なっているのがわかります。 
  • オレンジ色では、Spring Framework が Web サービスの呼び出しに Apache Commons HTTP Client を使用していることがわかります。 
  • 赤色では、スレッドが SocketInputStream.socketRead でスタックしたことがわかります。これは、スレッドが Web サービスの応答を待機していることを意味します。

[1]

capture

原因

以下に、一般的な原因を一部示します。

  1. Web サービスのホストにアクセスできない、ソケットが「接続タイムアウト」になる時間が設定されていないか、その設定時間が長すぎです(例:10分間)。
  2. Web サービスはアクティブですが、アプリケーションによって処理されていないエラーに応答しています。
  3. Web サービスはアクティブですが、応答が遅すぎる、または応答中にハングします。ソケットの「読み取りタイムアウト」が設定されていないか、長時間に設定されています。  スレッドが無期限に応答を待っています。
  4. スレッドプールが、一度に1つの要求を許可するように設定されています。  これにより、同時実行のリクエストスレッドが待機します。

解決策

これらの問題のソリューションは次のとおりです。

  1. 「接続タイムアウト」を適切な値、例えば 3 秒間など、で設定してください。
  2. 「読み取りタイムアウト」を適切な値に設定します。この値は、希望する応答の実行時間によって異なります。ほとんどの小規模な Web サービスでは、10秒が妥当です。 しかし、大容量のファイルを大量に処理または送受信する Web サービスでは、読み取りのタイムアウト設定値が大きくなります。
  3. 効果的にマルチスレッドを管理する方法においては、httpclient や Web サービスクライアントライブラリのマニュアルを参照してください。例えば、Apache の一般的な HTTP クライアント 3.x おいては、このページを参照することができます。
  4. サービス呼び出しからの応答をキャッシュします。  これは、同じパラメーターを使用してサービスを呼び出すとき、または同じ結果が複数回得られる場合に適用されます。
  5. データが共有されている(ユーザ固有ではなく)場合、バックグラウンドスレッドで Web サービスを事前に呼び出し、後で使用するために結果を保存します。  例えば、sling ジョブ、sling スケジューラ、あるいは AEM ポーリングインポーターを使用してバックグラウンドスレッドを管理したりできます。
  6. 発信が多い場合は、バックオフアルゴリズムを実装しエラーを処理します。  これは、アプリケーションがサービスを呼び出して X 回失敗した場合、一定の時間を停止し、代わりにエラーを直ちに報告します。  それで、X 回再試行してみます。再度失敗したりタイムアウトになった場合は、待機時間を長めにしてみたりします。  この方法は、通常、最大キャップ時間(別称「Truncated Exponential Back-off Algorithm」)と待機時間に大幅な増加が伴います。

本作品は Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License によってライセンス許可を受けています。  Twitter™ および Facebook の投稿には、Creative Commons の規約内容は適用されません。

法律上の注意   |   プライバシーポリシー