7

我目前正在研究http://truevfs.java.net,这是一个 Java 虚拟文件系统。TrueVFS 是模块化的,使用插件架构在运行时加载功能,无需进行任何配置。一些可选插件使用平台 MBeanServer 来注册具有已定义 ObjectName 的 MBean,以进行监视和管理。

现在我的一些用户正在他们的 WAR 中捆绑 TrueVFS JAR 以部署到 Tomcat 等。除非它们包含启用 JMX 的插件之一并在不同的上下文中部署多个 WAR 实例,否则这工作正常。

这不起作用,因为每个 Web 应用程序都有自己的启用 JMX 插件的类加载器定义,但是它们都将共享相同的平台 MBeanServer 并使用相同的 ObjectNames 来注册它们的 MBean,因此会发生冲突。

现在我该如何解决这个问题?我已经抽象了 MBeanServer 查找,以便可以将其提取到另一个插件中,但是我无法确定一个普遍适用的策略,我应该使用哪个 MBeanServer 来注册我的 MBean。

我搜索了这个主题并找到了一些WebLogic 的文档,这表明我应该使用 JNDI 查找 MBeanServer。但是,这似乎特定于 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(); }

正如预期的那样,该程序注册了两个 Messenger MBean,找到它们并打印它们的“Hello world!”。信息。

但是,这种解决方案也有缺点:

  • 我必须模拟一个附加属性作为标识符。理想情况下,这将是类加载器的标识符,这样我就可以保持通用性,即不必仅为 Web 应用程序做特殊考虑。
  • 现在查找 MBean 需要考虑多个类加载器的特殊情况,即 MBean 的多个实例,它们的区别仅在于它们的附加限定符,即使应用程序独立运行。

这些都是严重的限制,但我似乎没有更好的选择,所以我可能会走这条路。

4

1 回答 1

5

您可以为每个 war 模块重新创建一个新的 MBeanServer。但是,当从 JSR-160 客户端外部查询它们时,您还需要指定 MBeanServer。

当您使用Jolokia时,您可以透明地合并 JVM 的所有 MBeanServer。但是,当您拥有具有相同名称的 MBean 并且只有一个可以访问时,这在这里也无济于事。

对于这种情况,我的解决方案是使用相同的 MBeanServer,但使用不同名称的 MBean。除了其他属性之外,您可以为这些 MBean 使用完全正交的域,或者在名称中添加额外的“限定符”键值对之类的东西。当我期望典型情况下只有一个 MBean 时,我首先尝试添加具有固定名称的 MBean。如果失败,我",qualifier=..."会使用自动生成的值向名称添加另一部分,该值可以由某个值(如 WAR 名称)唯一标识,甚至是可配置的值。

事实上,从客户端的角度来看,处理多个 MBeanServer 确实很痛苦,因此使用 JMX 作为具有唯一性(可能是部分生成的 MBean 名称)的全局命名空间是一个简单的选择。

于 2012-11-03T09:36:43.863 回答