7

私は現在、Java の仮想ファイル システムであるhttp://truevfs.java.netに取り組んでいます。TrueVFS はモジュール式で、プラグイン アーキテクチャを使用して実行時に機能をロードします。何も構成する必要はありません。一部のオプションのプラグインは、プラットフォーム MBeanServer を使用して、監視および管理のために定義済みの ObjectName で MBean を登録します。

現在、一部のユーザーは、Tomcat などに展開するために、WAR に TrueVFS JAR をバンドルしています。これは、JMX 対応プラグインの 1 つを含めて、異なるコンテキストで WAR の複数のインスタンスをデプロイしない限り、正常に機能しています。

各 Web アプリには JMX 対応プラグインの独自のクラス ローダー定義があるため、これは機能しませんが、それらはすべて同じプラットフォーム MBeanServer を共有し、同じ ObjectNames を使用して MBean を登録するため、衝突が発生します。

さて、どうすればこの問題を解決できますか? MBeanServer ルックアップを抽象化して別のプラグインに抽出できるようにしましたが、MBean を登録するために使用する MBeanServer を一般的に適用できる戦略を特定できません。

この件についてグーグル検索したところ、JNDI を使用して MBeanServer を検索する必要があることを示すWebLogic のドキュメントが見つかりました。ただし、これは WebLogic に固有のようです。

一般的な画一的なアプローチはありませんか?


アップデート:

追加のプロパティを使用して、Web アプリで定義されたクラス ローダーを識別するための簡単な概念実証を次に示します。

import java.lang.management.ManagementFactory;
import javax.management.JMX;
import javax.management.MBeanServer;
import javax.management.ObjectName;

public class Messenger implements MessengerMXBean {

    private static MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();

    public static void main(String[] args ) throws Exception {
        register("one");
        register("two");
        find();
        System.out.println("Waiting for interrupt...");
        Thread.sleep(Long.MAX_VALUE);
    }

    private static void register(String context) throws Exception {
        mbs.registerMBean(new Messenger(),
                new ObjectName(":type=Messenger,context=" + context));
    }

    private static void find() throws Exception {
        for (ObjectName name : mbs.queryNames(new ObjectName(":type=Messenger,*"), null))
            System.out.println(JMX.newMXBeanProxy(mbs, name, MessengerMXBean.class).getMessage());
    }

    public String getMessage() { return "Hello world!"; }
}

public interface MessengerMXBean { String getMessage(); }

予想どおり、このプログラムは 2 つの Messenger MBean を登録し、それらを見つけて、"Hello world!" を出力します。メッセージ。

ただし、このソリューションには欠点があります。

  • 追加のプロパティを識別子としてモックアップする必要があります。理想的には、これはクラス ローダーの識別子であり、これにより汎用性を保つことができます。つまり、Web アプリのためだけに特別な考慮事項を行う必要はありません。
  • MBean を検索するには、アプリケーションがスタンドアロンで実行されている場合でも、複数のクラス ローダーの特殊なケース、つまり追加の修飾子だけが異なる MBean の複数のインスタンスを考慮する必要があります。

これらは深刻な制約ですが、これ以上の選択肢がないように思われるので、おそらくこの方法を使用します。

4

1 に答える 1

5

war モジュールごとに新しい MBeanServer を新たに作成できます。ただし、JSR-160 クライアントの外部からクエリを実行する場合は、MBeanServer も指定する必要があります。

Jolokiaを使用すると、JVM のすべての MBeanServer が透過的にマージされます。ただし、同じ名前の MBean があり、到達できるのは 1 つだけである場合にも、これは役に立ちません。

この状況に対する私の解決策は、同じ MBeanServer を使用することですが、名前が異なる MBean を使用することです。これらの MBean に完全に直交するドメインを使用するか、他のプロパティに加えて、名前に追加の「修飾子」キーと値のペアのようなものを追加することができます。一般的な状況で MBean が 1 つしかないと予想される場合は、最初に固定名で MBean を追加しようとします。これが失敗した場合は",qualifier=..."、自動生成された値、何らかの値 (WAR 名など) で一意に識別できる値、または構成可能な値のいずれかを使用して、名前に別の部分を追加します。

実際、複数の MBeanServer を扱うことは、クライアントの観点からは非常に面倒なので、JMX を一意の (おそらく部分的に生成された MBean 名) を持つグローバル名前空間として使用するのが簡単なオプションです。

于 2012-11-03T09:36:43.863 に答える