メッセージングパフォーマンスの調整
Liferay DXP 2023.Q3/Portal GA92 以前 サポート対象外
このチュートリアルで説明するメッセージング API は、Liferay DXP 2023.Q3/Portal GA92 以降では利用できません。
メッセージングのパフォーマンスは、送信先で調整されます。 パフォーマンスは、送信先の種類、メッセージリスナーが必要とする処理量、およびメッセージを処理するために利用可能なスレッドプールによって異なります。
目的地の種類は以下の3つです。
並行目的地
- ここで送信されたメッセージはキューに入れられます。
- スレッドプールのワーカースレッドは、登録されたメッセージリスナーにメッセージを配信します。1つのメッセージリスナーにつきメッセージごとに1つのワーカースレッドがあります。 スレッドは、同じメッセージを宛先のメッセージリスナーに同時に配信します。
シリアル宛先
- ここで送信されたメッセージはキューに入れられます。
- スレッドプールのワーカースレッドは、登録されたメッセージリスナーにメッセージを配信します(メッセージごとに1つのワーカースレッド)。
同期宛先
- ここで送信されるメッセージは、メッセージリスナーに直接配信されます。
- メッセージを送信するスレッドは、すべてのメッセージリスナーにもメッセージを配信します。
適切な送信先タイプを使用することで、さまざまな方法でメッセージを送信できます。
宛先タイプの互換性
以下は、各宛先タイプと 非同期メッセージング、 デフォルト同期メッセージング、および 直接同期メッセージング との互換性です。
| 宛先タイプ | 非同期メッセージング | デフォルトの同期メッセージング | 直接同期メッセージング |
|---|---|---|---|
| パラレル | ✔ | ✔ | ✘ |
| シリアル | ✔ | ✔ | ✘ |
| 同期 | ✘ | ✘ | ✔ |
ここではまず、あるプロジェクトのメッセージングパフォーマンスを検証することから始めます。 次に、APIを使用して宛先の統計情報を取得し、宛先を設定します。 最後に、サンプル送信先の設定を再構成し、サンプルを再実行して、統計情報を確認します。
サンプルプロジェクトにおけるメッセージングの監視
このサンプルプロジェクトでは、Gogoシェルコマンドを使用して、宛先を作成し、メッセージリスナーを登録し、宛先の統計情報を一覧表示します。
Liferay の新しいインスタンスを起動するには、次のコマンドを実行します。
docker run -it -m 8g -p 8080:8080 liferay/portal:7.4.3.132-ga132
http://localhost:8080 で Liferay にサインインしてください。 メールアドレス test@liferay.com とパスワード test を使用してください。 プロンプトが表示されたら、パスワードを learn に変更してください。
次に、以下の手順に従ってください。
-
サンプルをダウンロードして解凍してください。
curl https://resources.learn.liferay.com/examples/liferay-w3r2.zip -Ounzip liferay-w3r2.zip -
サンプルプロジェクトのモジュールをビルドしてデプロイします。
cd liferay-w3r2./gradlew deploy -Ddeploy.docker.container.id=$(docker ps -lq)注記このコマンドは、モジュール JAR を Docker コンテナ上の
/opt/liferay/osgi/modulesにコピーすることと同じです。 -
Dockerコンテナコンソールは、モジュールの起動を確認し、宛先構成を報告します。
com.acme.w3r2.charlie.impl_1.0.0 [1390] com.acme.w3r2.able.impl_1.0.0 [1388] [W3R2AbleMessagingConfigurator:27] {_destinationName=acme/w3r2_able, _destinationType=serial, _maximumQueueSize=2147483647, _rejectedExecutionHandler=null, _workersCoreSize=2, _workersMaxSize=5} com.acme.w3r2.baker.impl_1.0.0 [1389] を開始しました -
ブラウザで
http://localhost:8080にアクセスして Liferay インスタンスを開き、認証情報を使用してサインインしてください。 -
スクリプトコンソール を開きます。
-
スクリプト欄に、以下のGroovyコードを実行してメッセージを送信してください。
import com.liferay.portal.kernel.messaging.*; MessageBusUtil.sendMessage( "acme/w3r2_able", new Message() { { setPayload("foo"); } }); -
W3R2BakerMessageListenerManagerのメッセージリスナーがメッセージを受信したことを確認してください。[acme/w3r2_able-2][W3R2BakerMessageListenerManager:30] メッセージペイロード foo を受信しました [acme/w3r2_able-2][W3R2BakerMessageListenerManager:30] メッセージペイロード foo を受信しました [acme/w3r2_able-2][W3R2BakerMessageListenerManager:30] メッセージペイロード foo を受信しました [acme/w3r2_able-2][W3R2BakerMessageListenerManager:30] メッセージペイロード foo を受信しました [acme/w3r2_able-2][W3R2BakerMessageListenerManager:30] メッセージペイロード foo を受信しました -
Gogoシェル を開きます。
-
Gogoシェルコマンドフィールドで
w3r2:listDestinationStatsコマンドを実行して、宛先の統計情報を取得します。w3r2:listDestinationStats -
acme/w3r2_able宛先の 10 個のリスナーと送信されたメッセージ数を確認します。[pipe-w3r2:listDestinationStats][W3R2CharlieOSGiCommands:29] acme/w3r2_able アクティブスレッド数 0、現在のスレッド数 1、最大スレッド数 1、最大 スレッドプールサイズ 1、メッセージリスナー数 10、最小スレッドプールサイズ 1、保留中の メッセージ数 0、送信済みメッセージ数 1
この例の3つのモジュールは、宛先を設定し、10個のメッセージリスナーを登録し、宛先の統計情報を一覧表示するためのGogoシェルコマンドを提供します。
W3R2AbleMessagingConfigurator が w3r2-able-impl でアクティブ化されると、 acme/w3r2_able 宛先を構成し、 DestinationConfigurationの toString() の値をログに記録します。
@Activate
private void _activate(BundleContext bundleContext) {
DestinationConfiguration destinationConfiguration =
DestinationConfiguration.createSerialDestinationConfiguration(
"acme/w3r2_able");
if (_log.isInfoEnabled()) {
_log.info(destinationConfiguration.toString());
}
Destination destination = _destinationFactory.createDestination(
destinationConfiguration);
_serviceRegistration = bundleContext.registerService(
Destination.class, destination,
MapUtil.singletonDictionary(
"destination.name", destination.getName()));
}
w3r2-charlie-implモジュール内のW3R2CharlieOSGiCommands は、同モジュールが提供する Gogo シェルコマンド「w3r2:listDestinationStats」を使用して、宛先統計情報をログに記録します。 W3R2CharlieOSGiCommandsの listDestinationStats() メソッドが宛先統計情報を取得する方法を調べます。
@Component(
property = {
"osgi.command.function=listDestinationStats", "osgi.command.scope=w3r2"
},
service = W3R2CharlieOSGiCommands.class
)
public class W3R2CharlieOSGiCommands {
public void listDestinationStats() {
if (_log.isInfoEnabled()) {
Destination destination = _messageBus.getDestination(
"acme/w3r2_able");
DestinationStatistics destinationStatistics =
destination.getDestinationStatistics();
_log.info(
StringBundler.concat(
"acme/w3r2_able アクティブ スレッド カウント "、
destinationStatistics.getActiveThreadCount()、
"、 現在のスレッド カウント "、
destinationStatistics.getCurrentThreadCount()、
"、最大スレッド数 "、
destinationStatistics.getLargestThreadCount()、
"、最大スレッドプールサイズ "、
destinationStatistics.getMaxThreadPoolSize()、
"、メッセージリスナー数 "、
destination.getMessageListenerCount()、
"、最小スレッドプールサイズ "、
destinationStatistics.getMinThreadPoolSize()、
"、保留中のメッセージ数 "、
destinationStatistics.getPendingMessageCount()、
"、送信メッセージ数 "、
destinationStatistics.getSentMessageCount()));
}
}
private static final Log _log = LogFactoryUtil.getLog(
W3R2CharlieOSGiCommands.class);
@Reference
private MessageBus _messageBus;
}
listDestinationStats() メソッドは、 _messageBus インスタンスを使用して Destination を取得し、次に宛先から DestinationStatistics インスタンスを取得します。 宛先は、最新の統計情報で DestinationStatistics オブジェクトを設定します。 このメソッドは、以下の宛先情報をログに記録します。
- アクティブなスレッド数
- 現在のスレッド数
- 最大スレッド数
- 最大スレッドプールサイズ
- メッセージリスナー数
- 最小(開始)スレッドプールサイズ
- 保留中のメッセージ数
- 送信されたメッセージ数
この同じAPIを使用して、メッセージの送信先を監視することもできます。
メッセージングの監視
メッセージングAPIは、送信先の設定を考慮した上で、送信先におけるメッセージングのパフォーマンスを監視することを可能にします。 以下の表は、宛先設定とメッセージング統計にアクセスするためのAPIメソッドを示しています。
宛先設定:
| 宛先設定 | APIメソッド |
|---|---|
| 宛先タイプ | Destination#getDestinationType() |
| 最大スレッドプールサイズ | DestinationConfiguration#getWorkersMaxSize() および DestinationStatistic#getMaxThreadPoolSize() |
| 最小スレッドプールサイズ | DestinationConfiguration#getWorkersCoreSize() および DestinationStatistic#getMinThreadPoolSize() |
| メッセージキューのサイズ | DestinationConfiguration#getMaximumQueueSize() |
目的地統計:
| 宛先統計 | APIメソッド |
|---|---|
| メッセージリスナー数 | Destination#getMessageListenerCount() |
| 保留中のメッセージの数 | DestinationStatistics#getPendingMessageCount() |
| 送信されたメッセージ数 | DestinationStatistics#getSentMessageCount() |
| 現在のスレッド数 | DestinationStatistics#getCurrentThreadCount() |
| アクティブなスレッド数 | DestinationStatistics#getActiveThreadCount() |
| 最大スレッド数 | DestinationStatistics#getLargestThreadCount() |
旅行先の統計データは、その場所の環境を考慮に入れて理解するようにしてください。
宛先統計を調べた上で、宛先を再設定することでパフォーマンスを改善できる可能性があります。
宛先タイプの変更
シリアル宛先を使用している場合で、メッセージが一部のメッセージリスナーに十分な速さで届かない場合は、最大スレッドプールサイズを増やす(次で説明します)か、並列宛先タイプに切り替えてみてください。 メッセージバスは、スレッドプールからのスレッドを使用して、並列の宛先メッセージリスナーを同時に処理します。
現在の DestinationConfiguration を目的のタイプのいずれかに置き換えることで、宛先タイプを切り替えることができます。 適切な DestinationConfiguration メソッドを使用して、新しい並列または直列の DestinationConfiguration を作成します。
createParallelDestinationConfiguration(String)createSerialDestinationConfiguration(String)
詳細については、 サンプル宛先の再設定 を参照してください。
メッセージキューとスレッドプールの設定
各シリアルおよびパラレル宛先には、メッセージキューと専用のスレッドプールが備わっています。
キューが満杯のときにメッセージが到着した場合、宛先の RejectedExecutionHandler がメッセージを処理します。 デフォルトのハンドラはメッセージを破棄し、警告をログに記録します。 デフォルトの最大メッセージキューサイズはJavaの最大整数値ですが、必要に応じて小さくすることもできます。
メッセージバスは、宛先のスレッドプールからメッセージリスナー処理スレッドを取得します。 プールには開始サイズと最大サイズがある。
これらの DestinationConfiguration メソッドを使用すると、最大メッセージキューサイズ、拒否された実行ハンドラ、スレッドプールの開始サイズ (コアサイズ)、およびスレッドプールの最大サイズを変更できます。
setMaximumQueueSize(int maximumQueueSize)setRejectedExecutionHandler(RejectedExecutionHandler rejectedExecutionHandler)setWorkersCoreSize(int workersCoreSize)setWorkersMaxSize(int workersMaxSize)
次に、サンプル宛先を再設定します。
サンプル宛先を再構成する
ここでは、例の acme/w3r2_able 宛先を以下の設定で再構成します。
- 宛先タイプ:
parallel - 開始スレッドプールサイズ:
10 - 最大スレッドプールサイズ:
20
手順は以下のとおりです。
-
DestinationConfigurationを、W3R2AbleMessagingConfiguratorの_activate(BundleContext)メソッドをこのコードに置き換えることで、別のを使用してください。@Activate private void _activate(BundleContext bundleContext) { DestinationConfiguration destinationConfiguration = DestinationConfiguration.createParallelDestinationConfiguration( "acme/w3r2_able"); destinationConfiguration.setWorkersCoreSize(10); destinationConfiguration.setWorkersMaxSize(20); if (_log.isInfoEnabled()) { _log.info(destinationConfiguration.toString()); } Destination destination = _destinationFactory.createDestination( destinationConfiguration); _serviceRegistration = bundleContext.registerService( Destination.class, destination, MapUtil.singletonDictionary( "destination.name", destination.getName())); } -
モジュールを再デプロイしてください。
./gradlew deploy -Ddeploy.docker.container.id=$(docker ps -lq) -
Dockerコンテナコンソールは、
w3r2-able-implモジュールの起動を確認し、宛先構成を報告します。com.acme.w3r2.able.impl_1.0.0 [1388] [W3R2AbleMessagingConfigurator:27] {_destinationName=acme/w3r2_able, _destinationType=parallel, _maximumQueueSize=2147483647, _rejectedExecutionHandler=null, _workersCoreSize=10, _workersMaxSize=20} -
このGogoシェルコマンドを実行して、メッセージリスナーモジュール(Acme W3R2 Baker実装)のIDを取得します。
lb | grep W3R2各行は、対応するモジュールのID番号で始まります。
1388|アクティブ | 10|Acme W3R2 Able実装 (1.0.0)|1.0.0 1389|アクティブ | 10|Acme W3R2 Baker実装 (1.0.0)|1.0.0 1390|アクティブ | 10|Acme W3R2 Charlie実装 (1.0.0)|1.0.0 -
以下のGogoシェルコマンドを使用してメッセージリスナーモジュールを再起動し、メッセージリスナーを宛先置換にバインドします。 番号をモジュールのIDに置き換えてください。
停留所1389開始 1389 -
スクリプトコンソールで以下のGroovyコードを再度実行して、別のメッセージを送信してください。
import com.liferay.portal.kernel.messaging.*; MessageBusUtil.sendMessage( "acme/w3r2_able", new Message() { { setPayload("foo"); } }); -
Gogoシェルで
w3r2:listDestinationStatsコマンドを実行して、宛先の統計情報を取得します。w3r2:listDestinationStats
このようなログメッセージが表示されれば、新しい設定が正しく適用されたことが確認できます。
[pipe-w3r2:listDestinationStats][W3R2CharlieOSGiCommands:29] acme/w3r2_able
アクティブスレッド数 0、現在のスレッド数 10、最大スレッド数 10、最大
スレッドプールサイズ 20、メッセージリスナー数 10、最小スレッドプールサイズ 10、
保留中のメッセージ数 0、送信済みメッセージ数 2
これで、宛先でのメッセージングを監視し、宛先設定を調整する方法がわかりました。 パフォーマンスを最適化するために、さまざまな設定をテストできます。
関連トピック