問題
-
ConfigurationModelListenerを実装したモデルリスナーを使って、システム設定の変更を追跡するモジュールを開発した。 すべてが正常に機能しているが、このモジュールが両方のノードで実行されるという問題がある。 通常、ノード1でリクエストが発生すると、対応するアクションがノード1で行われる。 しかし、このシナリオでは、ノード1とノード2の両方で実行される。
再現の手順:
1. 2 ノードのクラスタをセットアップする。
2. ノードの1つで、コントロールパネル > システム設定 > セキュリティ > 監査にアクセスし、有効のチェックボックスをオフにして保存します。 (この設定の初期保存を行うだけ)
3. アタッチされたPoCモジュールを両方のノードにデプロイする。 (Liferay-configlistener-clusterIssue.zip)
4.
結果:両方のノードで出力され、両方のノードで呼び出しが発生していることがわかる。
期待されること:デプロイ可能なJARを呼び出すと、クラスタ化されたサーバーの一方のノードでのみログが出力されるはずである:期待されるのは、デプロイ可能なJARを呼び出すと、クラスタ化されたサーバーの1つのノードにのみログが出力されることです。
環境
- 7.4
解像度
-
私たちのチームは
ConfigurationModelListenerの再設計に取り組んでいます。 現在の設計は、コンフィギュレーションの検証のみを目的としており、クラスタ全体で実行することは想定していない。 この再設計には時間がかかりますので、ConfigurationModelListener を使用して、次のような代替案を提案します:
import org.osgi.service.cm.ConfigurationEvent;
import org.osgi.service.cm.ConfigurationListener;
import org.osgi.service.component.annotations.Component;
@Component(service = ConfigurationListener.class)
public class TracingConfigurationListener implements ConfigurationListener {
@Override
public void configurationEvent(ConfigurationEvent configurationEvent) {
System.out.println("############Configuration Event : " + configurationEvent.getType() + " for " + configurationEvent.getPid());
}
}
この解決策は、ConfigurationModelListenerの代わりに、ConfigurationListenerを作成し、 、設定イベントをリッスンすることに基づいています。configurationEventメソッドのみを実装する必要があります。
先に提供したPoCでは、クラスGenericConfigurationListenerが作成さ れ、メソッドonBeforeSaveが実装されています 。 私たちの提案では、次のことが必要だ:
-
ConfigurationModelListenerの代わりにConfigurationListenerを実装するようにクラスを適応する。 -
onBeforeSaveのロジックを、新たに必要なメソッドconfigurationEventに実装する。 -
configurationEvent.getPid()がリッスンしたいコンフィギュレーション(com.liferay.portal.security.audit.configuration.AuditConfiguration)と等しいことを確認します。 - 必要な種類の
configurationEvent(ConfigurationEvent.CM_UPDATED、ConfigurationEvent.CM_DELETED)のロジックだけを適用する必要があります。
物事を明確にするために、例えば私たちのクラスを見てみましょう。 https://github.com/liferay/liferay-portal/blob/88cf28caf54d71b332b6fd1bc2bb07ed29b847a7/modules/apps/portal-security/portal-security-ldap-impl/src/main/java/com/liferay/portal/security/ldap/internal/configuration/LDAPConfigurationListener.java を見てください。を実装しています。.
また、もしあなたのコードが各ノード上で実行される必要があるのであれば、それらを別のクラスに抽出することができます。ClusterableアノテーションかClusterExecutorUtilを使うことができます: https://help.liferay.com/hc/en-us/articles/360018154832-Liferay-s-Clustering-API
要約すると
-
ConfigurationModelListenerロジックが変更され、おそらくクラスタ内で実行されなくなります。 - コンフィギュレーションの変更をリッスンしたい場合は、(再設計されることを考慮した)現在のアプローチを使用するか、上記の私たちのアプローチに従うことができます。
- 設定変更に耳を傾けたら、
@Clusterable アノテーションまたはClusterExecutorUtilを使って好きなコードを実行できます。
-
追加情報
- https://liferay.atlassian.net/browse/LPD-1755
- https://liferay.atlassian.net/browse/LPD-8476