JMX的一些讨论

最近工作中用到了JMX,遇到了一些问题,正好记录一下。
spring的jmx配置文件就是参考文档的,见最后。

稍稍说明三点:
(1) Registry bean用来注册一个rmi的连接器,告知开启的端口号。
(2) ServerConnector用来构建服务器端的连接,这里用的是iiop的连接方式。objectName和serviceUrl要匹配。
(3) Assembler配置了对外暴露的mbean,这里就是把mbeanName这个接口的方法都暴露出去。

在使用的过程中,我碰到了一些问题和疑问,总结如下:
1、 本机启动应用之后,发现jmx端口没有打开,可是用jconsole连接serviceUrl的服务,却可以连接的上?

因为这个时候serviceUrl就是本机地址127.0.0.1的,这个通信连接是本机进程之间的通信。进程间的通信(Interprocess Communication)有多种方式,主要有以下几种:
◎ 文件映射:一个进程建立一个文件映射对象,写入数据,另一个进程从中取出数据,也就是这两个进程共享了文件中的数据。
◎ 共享内存:与文件映射类似,一个进程把数据写入内存,另一个进程从内存中取出数据。
◎ 管道:两个进程之间的有序通道。
◎ 套接字(socket):网络应用大多使用它。

所以尽管我连接的是“service:jmx:iiop://10.13.37.62:9099/”(10.13.37.62是本机IP),但其实并不是通过socket来通信的,估计是通过共享内存或者文件映射来通信的,具体实现我并不清楚。所以,这个时候,jmx的端口并没有开启。
加上registry bean的配置之后,可以看到JMX的端口9099端口就可以打开了。
所以,不要以为本地可以连接就OK了啊~~


2、 RMI-IIOP是什么?

在RMI-IIOP出现之前,分布式程序设计只有两种选择,RMI和CORBA。RMI就是远程方法调用,仅用于java对java的分布式远程调用,所以RMI对java开发者而言相当透明而且易于实现,而CORBA是面向对象的分布式系统的建立标准,对语言独立,接口采用了非常通用的标准。RMI-IIOP结合了RMI的简单和CORBA的多语言的优点。
我这次用的是iiop,如果要指定其他URL或者要用 MBeanServer 注册 JMXConnectorServer, 要使用相应的 serviceUrl 和 ObjectName 属性。


3、 关于远程调用的参数调用

讲到这里,我顺便把Java中的传值调用好好写写。
Java中,如果传递的是基本数据类型(如int, double, char等)的参数的话,实际传入方法内部的是输入参数的一个拷贝,这个拷贝进入方法之后就作为局部变量,所有在方法内部的操作都是针对这个局部变量来进行的,方法结束之后,这个局部变量就完成了使命。所以在方法内部改变参数的值,并不会对输入的参数造成影响。这也就是为什么像下面的swap方法不起作用的原因。


public static void main(String[] args) {
int i = 2;
int j = 3;
swap(i,j);
System.out.println("i===" + i);
System.out.println("j===" + j);
}

private static void swap(int pram1, int pram2) {
int temp = pram2;
pram2 = pram1;
pram1 = temp;
}

输出结果:
i===2
j===3


如果参数是对象的话,传递的是这个对象引用的一个copy。一个对象在建立的时候,会创建一个指向这个对象的引用a。如下图所示:
[img]http://dl.iteye.com/upload/attachment/160056/b370bb6a-68c6-3815-964c-cc11b7e19404.bmp[/img]
当把这个对象作为参数传递给方法的时候,会重新拷贝一个对象的引用b,这个时候,引用a和b都指向了同一个对象。所以,尽管方面里面的局部变量b与实际创建对象时候的a并不是同一个引用,但是它们指向的都是同一个对象。在方法里修改b的属性的时候,其实也就是修改b指向的对象的属性。
[img]http://dl.iteye.com/upload/attachment/160058/9b3b87e9-fbb3-3eea-90b6-2c036d0ecdc3.bmp[/img]
举例:

public static void main(String[] args) {
TestClass a = new TestClass();
a.setClassName("class a");
System.out.println("before changeClassName======className is " + a.getClassName());
changeClassName(a, "class b");
System.out.println("after changeClassName======className is " + a.getClassName());
}

private static void changeClassName(TestClass object, String className) {
bject.setClassName(className);
}

class TestClass{
private String className;

public String getClassName() {
return className;
}

public void setClassName(String className) {
this.className = className;
}
}

上面代码的执行结果为:
before changeClassName======className is class a
after changeClassName======className is class b


对于远程调用来说,大体上的规则还是一样的,只是因为数据要在client和server端进行传输,所以要把参数序列化与反序列化。
比如,本地为客户端client,要调用server端的userService.changeUserName(User user)这个方法,我在client上新建了一个user,现在这个user是client上的一个对象,然后通过RMI来调用远程方法changeUserName(user),那么就需要把user这个对象序列化,传递给server,然后在server端反序列化user,创建一个User对象,做相应的修改操作之后,再把server端的这个user对象序列化了传回client。最后,client反序列化server传递过来的user对象,再修改client本地的对应的user对象。所以,修改user name的操作就是在服务器上做的。

最后,附上spring的jmx配置文件:

<bean id="registry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean"> <property name="port" value="9099"></property>
</bean>
<bean id="mbeanName" class="com.***.jmx.***MBeanImpl">
<constructor-arg value="9099" />
</bean>
<bean id="assembler" class="org.springframework.jmx.export.assembler.InterfaceBasedMBeanInfoAssembler">
<property name="managedInterfaces">
<value>com.***.jmx.***MBean</value>
</property>
</bean>
<bean id="namingStrategy" class="org.springframework.jmx.export.naming.KeyNamingStrategy" >
</bean>
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter" lazy-init="false">
<property name="beans">
<map>
<entry key="bean:name=***Bean" value-ref="mbeanName"/>
</map>
</property>
<property name="server" ref="mbeanServer"/>
<property name="autodetect" value="false"/>
<property name="assembler" ref="assembler" />
<property name="namingStrategy" ref="namingStrategy"/>
</bean>
<bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean">
</bean>
<!-- Expose JMX over RMI -->
<bean id="serverConnector" class="com.***.jmx.ConnectorServerFactoryBean" depends-on="registry">
<property name="objectName" value="connector:name=iiop" />
<property name="server" ref="mbeanServer"/>
<property name="serviceUrl" value="service:jmx:iiop://localhost:9099" />
</bean>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值