在Tomcat,WebLogic,Glassfish等中使用哪个MBeanServer?

Chr*_*rle 6 tomcat jmx weblogic glassfish java-ee

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

现在,我的一些用户将TrueVFS JAR捆绑在他们的WAR中,以便部署到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(); }
Run Code Online (Sandbox Code Playgroud)

正如所料,该程序注册了两个Messenger MBean,找到它们并打印出它们的"Hello world!".信息.

但是,此解决方案存在缺点:

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

这些是严重的限制,但似乎我没有更好的选择,所以我可能会这样做.

Rol*_*Huß 5

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

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

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

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