使用MBean和Jolokia实现数据监控

静态MBean的定义

通过MBean的定义可以在系统运行时,查看系统内部的数据或执行系统内部的功能,真正的使用过程中静态MBean的使用是最多的。

定义的MBean必须实现以类名+MBean的接口

如下所示定义了一个MBean结构ShardInfo,所以为了使ShardInfo能够注册进MBeanServer中,需要定义接口ShardInfoMBean,并实现。

@Getter
@Setter
public class ShardInfo extends AbstractMXBean implements ShardInfoMBean {
    private String shardName;
    protected ShardInfo(String mBeanName, String mBeanType, String mBeanCategory) {
        super(mBeanName, mBeanType, mBeanCategory);
    }
}

mBeanName/mBeanType/mBeanCategory主要是对MBean进行分类,对应效果如图:
在这里插入图片描述

实现的XXMBean接口中,以getXX方法确定可以查询的字段

public interface ShardInfoMBean {
    String getShardName();
}

如上面代码所示,显示的字段为shardName。
在这里插入图片描述

可以触发方法,也是XXMBean接口中定义的方法,实现即为MBean中对应的实现

新增printShardName方法与实现

public interface ShardInfoMBean {
    String getShardName();

    void printShardName();
}
    @Override
    public void printShardName() {
        System.out.println("ShardName:" + shardName);
    }

在这里插入图片描述
手动触发该方法:
在这里插入图片描述
方法执行完成:
在这里插入图片描述

MBean注册

从上文已经知道对于静态MBean如何定义,通过JDK自带的ManagementFactory可以完成MBean的注册。核心逻辑如下所示:

    private boolean registerMBean() {
        boolean registered = false;
        try {
            // Object to identify MBean
            final ObjectName mbeanName = this.getMBeanObjectName();
            log.debug("Register MBean {}", mbeanName);
            // unregistered if already registered
            if (server.isRegistered(mbeanName)) {
                log.debug("MBean {} found to be already registered", mbeanName);
                try {
                    unregisterMBean(mbeanName);
                } catch (Exception e) {
                    log.warn("unregister mbean {} resulted in exception {} ", mbeanName, e);
                }
            }
            server.registerMBean(this, mbeanName);
            registered = true;
            log.debug("MBean {} registered successfully", mbeanName.getCanonicalName());
        } catch (Exception e) {
            log.error("registration failed.", e);
        }
        return registered;
    }

其中server是固定的:

private final MBeanServer server = ManagementFactory.getPlatformMBeanServer();

mbeanName全路径名称格式为BASE_JMX_PREFIX:type=XX,catagory=XX,name=XX具体拼接代码为:

    private ObjectName getMBeanObjectName() throws MalformedObjectNameException {
        StringBuilder builder = new StringBuilder(BASE_JMX_PREFIX)
                .append("type=").append(getMBeanType());

        if (getMBeanCategory() != null) {
            builder.append(",Category=").append(getMBeanCategory());
        }

        builder.append(",name=").append(getMBeanName());
        return new ObjectName(builder.toString());
    }

使用代码查询MBean属性与执行方法

    MBeanServer server = ManagementFactory.getPlatformMBeanServer();

    @Test
    public void testGetShardInfoMBean() throws MalformedObjectNameException, IntrospectionException, InstanceNotFoundException, ReflectionException, AttributeNotFoundException, MBeanException {
        ShardInfo shardInfo = new ShardInfo("sharInfo", "shard", "category1");
        shardInfo.setShardName("sunquan");
        shardInfo.register();
        MBeanInfo mBeanInfo = server.getMBeanInfo(shardInfo.getMBeanObjectName());
        //查询属性
        Assert.assertEquals(mBeanInfo.getClassName(), ShardInfo.class.getName());
        Assert.assertEquals("sunquan", server.getAttribute(shardInfo.getMBeanObjectName(), "ShardName"));
        //执行方法
        server.invoke(shardInfo.getMBeanObjectName(), "printShardName", null, null);
    }

如何避免每个静态MBean都要单独定义接口

目前考虑有下列两个方法:

  1. 开发MBean上的相关注解,触发在编译期其注入方法至接口类中
  2. 使用动态MBean实现
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值