CPUに負荷のかかるタスクが多すぎる:DXP 7.0の一般的なパフォーマンスの問題

この記事では、Liferay DXP 7.0内でCPUが多すぎるタスクの実行に関連する一般的なパフォーマンスの問題について説明します。この問題についての必要な情報とそのナビゲート方法を見つけるために、引き続き読んでください。

以下は、より一般的な原因と解決策の一部です。

  1. Minifier
  2. StripFilter
  3. GZipFilter
  4. パスワードハッシュ

解決

多くのCPUを集中的に使用するタスクを同時に実行すると、一部のサブスクライバーでパフォーマンスの問題が発生する可能性があります。 これは、さまざまなユースケースから生じる可能性のある一般化されたパターンです。 直面している問題の重大度に応じて、スレッドダンプには、そのようなタスクに取り組んでいる数十から数百のスレッドが含まれる場合があります。 CPU使用率が高くなり、応答時間が遅くなります。まれに、Liferayプラットフォームが応答しなくなったように見えることがあります。

より一般的な原因とその後の解決策について、以下の情報を確認してください。

Minifier

Minifierは、CSSおよびJavaScriptリソースをブラウザーに送信する前にそれらを縮小しようとします。 このアクションにより、ファイルのサイズが小さくなるため、ネットワーク帯域幅を節約できます。 ただし、CPUのパフォーマンスが低下します。

Minifierはデフォルトで有効になっていますが、以下のプロパティを portal-ext.propertiesminifier.enabled = false設定することで無効にできます。

スレッドダンプでは、次の文字列が数十回、場合によっては数百回表示されると、この問題が発生します。

com.liferay.portal.util.MinifierUtil._minifyCss

"http-/0.0.0.0:8280-336" daemon prio=10 tid=0x00007f8bfc282ea0 nid=0x2c0d runnable [0x00007f8aa6d27000]
   java.lang.Thread.State: RUNNABLE
    at java.util.regex.Pattern$CharProperty$1.isSatisfiedBy(Pattern.java:3689)
    at java.util.regex.Pattern$7.isSatisfiedBy(Pattern.java:5171)
    at java.util.regex.Pattern$7.isSatisfiedBy(Pattern.java:5171)
    at java.util.regex.Pattern$7.isSatisfiedBy(Pattern.java:5171)
    at java.util.regex.Pattern$CharProperty.match(Pattern.java:3694)
    at java.util.regex.Pattern$Curly.match0(Pattern.java:4158)
    at java.util.regex.Pattern$Curly.match(Pattern.java:4132)
    at java.util.regex.Pattern$Start.match(Pattern.java:3408)
    at java.util.regex.Matcher.search(Matcher.java:1199)
    at java.util.regex.Matcher.find(Matcher.java:592)
    at java.util.regex.Matcher.replaceAll(Matcher.java:902)
    at java.lang.String.replaceAll(String.java:2162)
    at com.yahoo.platform.yui.compressor.CssCompressor.compress(CssCompressor.java:345)
    at com.liferay.portal.util.MinifierUtil._minifyCss(MinifierUtil.java:59)
    at com.liferay.portal.util.MinifierUtil.minifyCss(MinifierUtil.java:38)

Spotifyの Online Thread Dump Analyzerを使用した同じスレッドダンプの別の例を次に示します。
spotify-performance-02.png

そのような場合、正確なスタックトレースが異なる場合があることに注意してください。 これらのスレッドはすべて実行中であるため、それらのスレッドはそれぞれのライフステージにあります。すべてのスレッドはCPU時間の進行を待っており、リソースの枯渇につながります。

これに対する解決策は、CSSとJavaScriptの縮小が必要かどうかを評価することです。 縮小が必要な場合は、さらにリソースが必要になることがあります。 サブスクライバーは、プラットフォームのクラスター化を検討するか、Webサーバーによるキャッシュや静的コンテンツのCDNサーバーへのオフロードによる追加リソースの使用を検討する必要があります。 ミニファイが必要ない場合は、前述の minifier.enabled プロパティを介して単純にオフにするだけで、CPUへの負荷を軽減できます。

StripFilter

StripFilterは、CPU使用率と引き換えにファイルが小さくなるという点でMinifierと似ています。 Liferayポータル6.2のコメントを参照してください: ストリップフィルターは、出力されたコンテンツから空白行を削除します。 これにより、ダイヤルアップしているユーザーのページレンダリングが高速化されます。
com.liferay.portal.servlet.filters.strip.StripFilter = true

CPUのコストに比べて実際のメリットはないため、最初からこれをオフにすることをお勧めします。 応答から新しい行を削除すると、スペースが節約されます。 ただし、コンテンツのgzip圧縮は非常に効率的であり、ファイルに改行があるかどうかは問題ではありません(極端なエッジケースを除く)。 さらに、ブラウザーがページをロードするのにかかる時間は、ほんのわずかに影響を受けるだけです。いずれにしても、ページのロードにかかる時間の大部分は、リソースがダウンロードされるのを待つために費やされます。

これは、ネットワークにもエンドユーザーにもこれを行うメリットはないが、CPUのパフォーマンスに影響があることを意味します。

このようなスレッドを見つけるには、文字列 StripFilter.strip検索します。 -特定のスレッドダンプに5つを超える発生がある場合は、これが原因で応答時間が低下していることに注意してください。 StripFilterを実際に実行しているスタックトレースの上部の下に含まれています。

"http-/0.0.0.0:8280-186" daemon prio=10 tid=0x00007f796c343250 nid=0x175e runnable [0x00007f7854134000]
   java.lang.Thread.State: RUNNABLE
    at java.nio.Buffer.checkIndex(Buffer.java:537)
    at java.nio.CharBuffer.charAt(CharBuffer.java:1238)
    at com.liferay.portal.kernel.util.KMPSearch.search(KMPSearch.java:218)
    at com.liferay.portal.kernel.util.KMPSearch.search(KMPSearch.java:200)
    at com.liferay.portal.servlet.filters.strip.StripFilter.processInput(StripFilter.java:410)
    at com.liferay.portal.servlet.filters.strip.StripFilter.strip(StripFilter.java:668)
    at com.liferay.portal.servlet.filters.strip.StripFilter.processFilter(StripFilter.java:399)

GZipFilter

GZipFilterの仕事は、ブラウザーに戻る応答を圧縮して、帯域幅を節約し、最終的にはページの読み込み時間を節約することです。 以下のプロパティによって制御されます
com.liferay.portal.servlet.filters.gzip.GZipFilter = true

GZipFilterは、StripFilterの影響を議論するときに以前に導入されました。そのセクションでは、とにかく応答をgzip圧縮するほうがより有益であるため、StripFilterを有効にする必要はないと述べました。 GZipFilter ではなく gzipping という単語を選択するのは意図的なものです。 Liferayは、可能であれば、コンテンツをgzip圧縮する別の方法を推奨しています。 たとえば、Apacheのmod_deflateには、別のサーバーのCPUが応答の圧縮を処理できるようにする別のボックスにあるという利点があります。 GZipFilterの主な役割は、応答の準備ができたらすべてを圧縮することなので、GZipFilterを見つけるのは困難です。 したがって、GZip関連のJavaクラスが最後に実行され、 GZipResponse $ 1 オブジェクトがロックされていることを確認することで、実行プロセスを確認できます。次に例を示します。

"http-/0.0.0.0:8280-324" daemon prio=10 tid=0x00007f8bfc26f460 nid=0x2c01 runnable [0x00007f8aa7933000]
   java.lang.Thread.State: RUNNABLE
    at java.util.zip.Deflater.deflateBytes(Native Method)
    at java.util.zip.Deflater.deflate(Deflater.java:430)
    - locked <0x00000006dd9bf380> (a java.util.zip.ZStreamRef)
    at java.util.zip.Deflater.deflate(Deflater.java:352)
    at java.util.zip.DeflaterOutputStream.deflate(DeflaterOutputStream.java:251)
    at java.util.zip.DeflaterOutputStream.write(DeflaterOutputStream.java:211)
    at java.util.zip.GZIPOutputStream.write(GZIPOutputStream.java:146)
    - locked <0x00000006dd9bf2f8> (a com.liferay.portal.servlet.filters.gzip.GZipResponse$1)
    at com.liferay.portal.kernel.servlet.ServletOutputStreamAdapter.write(ServletOutputStreamAdapter.java:54)

前述のように、GZipFilterに起因する、またはGZipFilterに関連するパフォーマンスの問題が現在ない場合でも、GZipFilterをオフにし、可能であれば他のサービスに依存することをお勧めします。

パスワードハッシュ

パスワードの比較は、ユーザーがフォームで指定したパスワードをハッシュしてから、データベースですでにハッシュされた(および保存された)パスワードと比較することによって行われます。 デフォルトでは、Liferayプラットフォームは計算負荷の高いアルゴリズムを使用し 。0PBKDF2とHMAC SHA1 1、160ビットハッシュ、128,000ラウンド。

以下は、暗号化アルゴリズムを設定するポータルプロパティです
passwords.encryption.algorithm = PBKDF2WithHmacSHA1 / 160/128000

CPUにこのような負荷がかかるのは、その動作方法が原因です。 入力テキストとソルトに疑似ランダム関数を使用してビットハッシュを作成し(デフォルト:160)、それを繰り返します(デフォルト:128,000)。 その結果、同時にログインする多くのユーザーが、CPUがすべてのリクエストを処理できるようになるまで、しばらくの間ポータルをロックする可能性があります。 以下は、ユーザーログインで動作するスレッドからのスタックトレースの先頭です。

"ajp--127.0.0.1-8009-198" daemon prio=10 tid=0x00007fcef1575600 nid=0xfe4d runnable [0x00007fced4138000]
   java.lang.Thread.State: RUNNABLE
    at com.sun.crypto.provider.HmacSHA1.engineReset(HmacSHA1.java:118)
    at javax.crypto.Mac.doFinal(Mac.java:547)
    at javax.crypto.Mac.doFinal(Mac.java:589)
    at com.sun.crypto.provider.PBKDF2KeyImpl.deriveKey(PBKDF2KeyImpl.java:178)
    at com.sun.crypto.provider.PBKDF2KeyImpl.(PBKDF2KeyImpl.java:121)
    at com.sun.crypto.provider.PBKDF2HmacSHA1Factory.engineGenerateSecret(PBKDF2HmacSHA1Factory.java:71)
    at javax.crypto.SecretKeyFactory.generateSecret(SecretKeyFactory.java:335)
    at com.liferay.portal.security.pwd.PBKDF2PasswordEncryptor.doEncrypt(PBKDF2PasswordEncryptor.java:77)

このような複数のスレッドが表示され、パスワードの暗号化に取り組んでいることは、Liferayプラットフォームに問題があり、ユーザーがログインしようとすると長い待機時間が報告される(またはすでに報告されている)ことを示します。

この問題にはいくつかの解決策があります。

  1. PBKDF2アルゴリズムの調整:
    1. 生成されるハッシュのサイズまたはラウンド数を小さくしてください。
    2. ただし、これらの手順はどちらも、考慮に入れる必要があるパスワード暗号化の強度を低下させます。
    3. ユーザーのパスワードを強制的にリセットする必要がある場合があります。
  2. 完全に別のアルゴリズムを使用する:
    1. PBKDF2 から計算量の少ない別のアルゴリズムに移動すると、CPUへの影響も緩和されます。
    2. これには、安全性の低い暗号化に移行することのマイナス面もあります。
    3. ユーザーのパスワードを強制的にリセットする必要がある場合があります。
  3. LDAPやSSOソリューションなどのサードパーティ認証サービスを使用する。
    1. 認証のプロセスはオフロードされ、Liferayプラットフォームは、資格情報の送信、セッションの管理などにより、サードパーティサービスとの交渉を処理します。
この記事は役に立ちましたか?
0人中0人がこの記事が役に立ったと言っています