Jmx 资源管理——demo篇

什么是Jmx

全称Java Management Extensions,可以将之理解为管理java资源的一个服务。当你运行一个java程序时,你可以通过它来掌握运行期间一些资源的情况,还可以在运行期间动态修改某些资源的值。

Jmx架构

至于Jmx的结构,可以参考下面这张图:
undefined
看起来挺复杂,不过没关系,一点一点来。
整体分三层:
- 最下层是资源层,也就是你要管理的资源,一般就是一个普通的java bean,包含你要管理的属性,以及你要进行的操作。只不过Jmx规定这些资源类要叫做XXXMBean,反正是要让Jmx认出来。
- 中间是代理层,你对于下面资源的操作都要通过代理层进行。这个很常见,许多java应用或者框架的结构都是这样,通过统一的代理进行操作,结构清晰,便于管理。
- 最上层是管理层,其实叫做管理层不太合适,因为这一层并不是直接管理资源,上文已经说过要通过代理层访问,因此这一层只不过给我们提供了连接代理层的方式。为了可以通过多种方式访问资源,如web端,控制台,或者通过编程API自己编写客户端,就需要对于不同的方式提供不同的适配器或连接器,如上图所示。

一个简单的demo

说了那么多,不如自己写一个简单的demo,理解更深刻。
首先要创建你要管理的资源,Jmx中一般是一个java bean,但是为了与一般的bean做区分,Jmx中的资源要实现以MBean为后缀的接口。几行代码,创建一个简单的MBean资源,如下:

public interface HelloWorldMBean {

    String getHelloWorld();

    void setHelloWorld(String hello);

}

public class HelloWorld implements HelloWorldMBean {

    private String helloWorld;

    @Override
    public String getHelloWorld() {
        return helloWorld;
    }

    @Override
    public void setHelloWorld(String helloWorld) {
        this.helloWorld = helloWorld;
    }

}

上面是一个以MBean为后缀的接口,下面是其实现类,也就是我们所说的Jmx中的资源。其实就跟一个普通的java bean差不多,除了命名需要遵守特定的规则,其他没什么不同(至于为什么需要这样命名,后文讨论)。此外,如果你想查询属性,则要设置get方法;需要修改属性,需要设置set方法。(此部分内容也在后文讨论)。

资源写好了,按照架构图,应该给它找个代理。仍旧几行代码,如下:

// get a default MBean server
MBeanServer server = ManagementFactory.getPlatformMBeanServer();

// the name of MBean
ObjectName mbeanName = new ObjectName("hello:name=HelloWorld");

// instance of helloWorldMBean and register
HelloWorldMBean helloWorldMBean = new HelloWorld();

// register MBean to server
server.registerMBean(helloWorldMBean, mbeanName);

配合着注释,简单解释就是,创建了一个供MBean注册的server,然后创建一个资源类的实例,将其注册上去。
不过有意思的是,代码中有个ObjectName,你可以把它当作你注册MBean时的代号。很简单,有许多资源要往你的server上注册,你要区分不同的MBean,就得有个代号,就是这个ObjectName。
创建ObjectName时,需要注意你传递的字符串需要遵从特定的格式,简单来说就是 {域名}:{key1}={value1},{key2}={value2}…{keyn}={valuen}。其实这个规则比较复杂,后文再讨论。

注册完了,如何使用呢? 很简单的几行代码,如下:

// get attribute
String helloWorld = (String) server.getAttribute(mbeanName, "HelloWorld");
System.out.println(helloWorld);//print null

// set attribute
server.setAttribute(mbeanName, new Attribute("HelloWorld", "hey"));

// get attribute after changing
helloWorld = (String) server.getAttribute(mbeanName, "HelloWorld");
System.out.println(helloWorld);//print hey

可以发现,将MBean注册到server之后,你只需通过ObjectName和属性名,就能修改和查询MBean中的属性值。(前提是你的MBean中有相应的set和get方法)
简单的demo这样就没了。。。好像没什么用啊, 如果只是更改bean的属性,那么我们直接调用set和get方法不是也可以吗?接下来我们试下用浏览器,通过web端,来获取和修改资源。

通过web控制的demo

我们基于上文简单的demo进行一下改造,不过在此之前要下载一个jar包,因为通过web控制所需的jar包并不在jdk自带的jar中,连接http://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloads-java-plat-419418.html, 选那个jmx-1_2_1-ri.zip就好,解压后把jmxtools那个jar加到classpath就可以了。

接下来,写代码。MBean不用改,在代理层的代码下面加上以下几行代码:

// create a html adapter so as to control jmx by web page 
ObjectName htmlAdapterName = new ObjectName("hello:name=htmlAdapter,port=8082");

// create a html adapter server, register and start
HtmlAdaptorServer adaptorServer = new HtmlAdaptorServer();
server.registerMBean(adaptorServer, htmlAdapterName);
adaptorServer.start();

将MBean注册到server之后,我们要在本地启动一个服务器以供来自web的连接。这个HtmlAdapterServer就是架构图中,供web端访问的适配器,同样需要把它注册到代理层的server中,然后调用start()方法,供web端访问的服务就开启了。
你只需要打开浏览器,输入localhost:8082,你就能看到当前你的jvm中注册的资源。仔细找找,你会发现刚刚自己写的MBean也在其中,点击这个连接,在MBean的视图中,你能看到对应属性,是否可读写,当前值。同时自己可以修改该属性。有点意思哈~
这里有个问题,你会发现,当你将ObjectName中的port属性改为其他端口时,仍旧只能访问8082端口,其他端口无效。所以也就意味着这个HtmlAdapterServer的端口值不是在这里设置的。这个问题我们后文再讲。

通过客户端控制的demo

上文中通过web控制的demo,可以作为查询、调控的界面,通过人工去控制。可是有些情况下,需要通过程序自动触发,比如你需要每隔十分钟更改一下资源值,这个时候通过人工控制就不现实了。
接下来我们写一个通过客户端控制的demo。
同样,我们的MBean不用改,仍是要改代理层的server,基于上文那个简单的demo,在将资源MBean注册到server后,添加如下几行代码

// register a port
LocateRegistry.createRegistry(9999);

// initial a url and get a jmx connector server instance
JMXServiceURL url = new JMXServiceURL(
    "service:jmx:rmi:///jndi/rmi://localhost:9999/jmxrmi");
JMXConnectorServer connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(url, null, server);

System.out.println("before connector server start....");

connectorServer.start();

System.out.println("connector server has started......");

这里我们创建了一个JMXConnectorServer,其实架构图中也已经画出了,是通过客户端访问的连接器。
本地注册一个端口,然后创建一个url传给这个connector,调用start()方法,这样就在本地启动了一个以供客户端连接的服务器。
我们发现这个url的格式有点奇怪,其实这也是Jmx规定的,比如以`service:jmx` 作为开头,默认实现rmi方式等,这个后文再讲。

服务器启动起来了,我们再建立一个自己的客户端。可以新建一个程序,几行代码,如下:

// new jmx url
JMXServiceURL url = new JMXServiceURL(
    "service:jmx:rmi:///jndi/rmi://localhost:9999/jmxrmi");

// connect
JMXConnector connector = JMXConnectorFactory.connect(url);

// get a connection instance
MBeanServerConnection connection = connector.getMBeanServerConnection();

//objectName must be same as which was register on server
ObjectName objectName = new ObjectName("hello:name=HelloWorld");

// get attribute before change
String helloWorld = (String) connection.getAttribute(objectName, "HelloWorld");
System.out.println("before" + helloWorld);

// set attribute
connection.setAttribute(objectName, new Attribute("HelloWorld", "client"));

helloWorld = (String) connection.getAttribute(objectName, "HelloWorld");
System.out.println("after : " + helloWorld);

结合注释,很容易看懂。通过相同的url,连接到已经创建好的服务器,之后的查询和修改资源的过程跟之前一样,不再多说。
本章先简单介绍几个简单的demo,也遗留下来很多问题,接下来的文章继续解答。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值