JMX笔记(一)

 上篇 JMX初体验 使用HtmlAdaptorServer提供的界面实现了调用MBean,除此之外,还可以使用rmi方式连接调用MBeanServer

 要连接,自然要有url:service:jmx:rmi://localhost:5000/jndi/rmi://localhost:6000/jmxrmi

 解释下:

  • service:jmx: 这个是JMX URL的标准前缀,所有的JMX URL都必须以该字符串开头。
  • rmi: 这个是connector server的传输协议,在这个url中是使用rmi来进行传输的。JSR 160规定了所有connector server都必须至少实现rmi传输,是否还支持其他的传输协议依赖于具体的实现。比如MX4J就支持soap、soap+ssl、hessian、burlap等等传输协议。
  • localhost:5000: 这个是connector server的IP和端口,这个端口可以称之为数据端口,该部分是一个可选项,如果省略的话,则connector server会随机任意选择一个可用的端口。
  • /jndi/rmi://localhost:6000/jmxrmi: 这个是connector server的路径,具体含义取决于前面的传输协议。比如该URL中这串字符串就代表着该connector server的stub是使用jndi api绑定在rmi://localhost:6000/jmxrmi这个地址。 这里的端口称之为通讯端口

理清一个思路:MBean注册在MBeanServer上-》JMXConnectorServer 关联MBeanServer使用jndi绑定在rmiregistry的rmi://localhost:6000/jmxrmi地址,并使用5000端口传输数据-》rmiregistry监听6000端口

 

先看下直接在jse下使用jmx

服务器端:

     //在指定端口上启动远程对象注册服务程序,启用RMI,对应于 JAVA_HOME/bin/rmiregistry.exe
        LocateRegistry.createRegistry(9797);
        // MBeanServer mbs = MBeanServerFactory.createMBeanServer();//不能在jconsole中使用
        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();//可在jconsole中使用
        //创建MBean
        HelloMBean mb = new Hello();
        //将MBean注册到MBeanServer中
        mbs.registerMBean(mb, new ObjectName("MyappMBean:name=controller"));

        JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://127.0.0.1:9797/h-server");
        JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);
        cs.start();

 

客户端:

@Test
    public  void jmxClient() throws IOException, MalformedObjectNameException {
        JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://127.0.0.1:9797/h-server");
        JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
MBeanServerConnection mbsc
= jmxc.getMBeanServerConnection(); HelloMBean helloMb = JMX.newMBeanProxy(mbsc,new ObjectName( "MyappMBean:name=controller" ),HelloMBean.class ); System.out.println("client call:"+helloMb.sayHello()); jmxc.close(); }

 

 现在的项目都离不开spring了,如果jmx不能够整合到spring,总显得不伦不类,网上参考了许多就是没成功,总算是熟悉了直接使用jmx,摸着石头过河总算过来了

server端配置

为了避免不必要的麻烦,自己定义个MBeanServer,大部分情况下,我们的bean并不是实现MBean结尾的接口,普通bean更常见,所以我用了MBeanExporter的beans属性进行手动注册

<bean id="mbServer" class="org.springframework.jmx.support.MBeanServerFactoryBean"/>
    <bean id="mbExporter" class="org.springframework.jmx.export.MBeanExporter" lazy-init="false"> 
    <property name="beans">
    <map>
      <entry key="MyappMBean:name=controller" value-ref="ffmMendService"/>
    </map>
    </property>
    <property name="server" ref="mbServer"/>
  </bean>
    <bean id="jmxConnectorServer" class="org.springframework.jmx.support.ConnectorServerFactoryBean" depends-on="registry">
        <property name="objectName">
            <value>connector:name=rmi</value>
        </property>
        <property name="serviceUrl">
            <value>service:jmx:rmi:///jndi/rmi://127.0.0.1:9797/ffmservice</value>
        </property>
        <property name="environment">
            <props></props>
        </property>
        <property name="server" ref="mbServer"/>
    </bean>
    <bean id="registry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean">
        <property name="port">
            <value>9797</value>
        </property>
    </bean>

注意说明:

1. lazy-init="false",这里一定不能设置成true,否则客户端会报”MyappMBean:name=controller找不到“异常

2. jmxConnectorServer需要设置environment属性,否则默认注入org.springframework.core.env.StandardEnvironment类型的evnironment,与ConnectorServerFactoryBean方法

public void setEnvironment(Properties environment) {
CollectionUtils.mergePropertiesIntoMap(environment, this.environment);
}

不匹配,报异常

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jmxConnectorServer' defined in class path resource [spring-remote.xml]: Initialization of bean failed; nested exception is org.springframework.beans.TypeMismatchException: Failed to convert property value of type 'org.springframework.core.env.StandardEnvironment' to required type 'java.util.Properties' for property 'environment'; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [org.springframework.core.env.StandardEnvironment] to required type [java.util.Properties] for property 'environment': PropertyEditor [org.springframework.beans.propertyeditors.PropertiesEditor] returned inappropriate value of type [org.springframework.core.env.StandardEnvironment]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:548)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:229)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:706)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
at mf.ffm.receiver.FFMReceiver.main(FFMReceiver.java:67)
Caused by: org.springframework.beans.TypeMismatchException: Failed to convert property value of type 'org.springframework.core.env.StandardEnvironment' to required type 'java.util.Properties' for property 'environment'; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [org.springframework.core.env.StandardEnvironment] to required type [java.util.Properties] for property 'environment': PropertyEditor [org.springframework.beans.propertyeditors.PropertiesEditor] returned inappropriate value of type [org.springframework.core.env.StandardEnvironment]
at org.springframework.beans.BeanWrapperImpl.convertIfNecessary(BeanWrapperImpl.java:480)
at org.springframework.beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java:511)
at org.springframework.beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java:505)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.convertForProperty(AbstractAutowireCapableBeanFactory.java:1517)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1476)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1216)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:538)
... 11 more
Caused by: java.lang.IllegalArgumentException: Cannot convert value of type [org.springframework.core.env.StandardEnvironment] to required type [java.util.Properties] for property 'environment': PropertyEditor [org.springframework.beans.propertyeditors.PropertiesEditor] returned inappropriate value of type [org.springframework.core.env.StandardEnvironment]
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:283)
at org.springframework.beans.BeanWrapperImpl.convertIfNecessary(BeanWrapperImpl.java:460)
... 17 more

 

客户端配置:

我不想在客户端定义服务接口,所以我使用了MBeanServerConnectionFactoryBean,等同于不用spring时

JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://127.0.0.1:9797/h-server");
JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();

获取了mbsc,而没用MBeanProxyFactoryBean

<bean id="jmxSCFB" class="org.springframework.jmx.support.MBeanServerConnectionFactoryBean">
  <property name="connectOnStartup" value="false" />
  <property name="serviceUrl">
    <value>service:jmx:rmi:///jndi/rmi://127.0.0.1:9797/ffmservice</value>
  </property>
</bean>

 

 

参考文章

1. jmx rmi 穿越防火墙问题及jmxmp的替代方案

2. MXBean(示例,出错代码)

3. Spring与JMX集成

4. JMX API

5. Chapter 20. JMX

posted @ 2016-01-25 14:05  未来的那啥  阅读(583)  评论(0编辑  收藏  举报