最近工作中用到了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。如下图所示:
当把这个对象作为参数传递给方法的时候,会重新拷贝一个对象的引用b,这个时候,引用a和b都指向了同一个对象。所以,尽管方面里面的局部变量b与实际创建对象时候的a并不是同一个引用,但是它们指向的都是同一个对象。在方法里修改b的属性的时候,其实也就是修改b指向的对象的属性。
举例:
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>
- 大小: 3.2 KB
- 大小: 3.9 KB
分享到:
相关推荐
书中不仅有对于基础知识的介绍,还有对于JMX开发中重大的体系架构问题的深入探讨,总结了大量JMX开发中的设计模式,并讨论了框架、安全性与性能等等。书中提供了几个典型的例子,兼顾各种开发平台,这些例子的代码...
本书还深入讨论了JMX与其他技术的集成,如JMX与Spring框架的整合,以及JMX在分布式系统中的应用,包括集群管理和跨节点通信。此外,书中还涉及到了安全管理,包括JMX连接的安全策略和认证机制,以确保管理系统安全...
"工具"标签暗示了博主可能讨论了使用JMX的一些实用工具,比如JConsole、VisualVM或者自定义的JMX客户端,它们可以用来查看和操作MBeans,进行性能分析和故障排查。 在压缩包`JmxEgs`中,可能包含了一些示例代码或...
接下来,我们讨论JMX的定时器服务。定时器服务允许用户在特定时间或定期发送自定义的通知。这对于计划任务执行、定期报告或者在预定时间执行的管理操作来说非常实用。通过定时器服务,你可以安排在任意时刻执行的...
接下来,我们讨论一下**Spring Schedule和Quartz的结合**,这是在Spring中实现定时任务的常见方式。Spring Schedule提供了基于`@Scheduled`注解的简单调度功能,而Quartz是一个更强大的作业调度库,适合复杂的调度...
标题"基于Spring+JMX+Tomcat实现资源动态管理"揭示了我们将讨论的核心技术栈。 首先,Spring是一个广泛使用的Java应用开发框架,它提供了依赖注入(DI)和面向切面编程(AOP)等功能,极大地简化了企业级应用的构建...
在本章《JMX实战(四)》中,我们将深入探讨最简单的MBean类型:标准MBean。标准MBean适用于具有稳定、已知接口的资源。这一章将介绍如何使用标准MBean来配置应用程序资源(如日志工具和应用属性),以及如何将应用...
现在,我们详细讨论这些知识点: 1. **TrueVFS**:TrueVFS是基于Java的虚拟文件系统库,它提供了一个统一的接口来操作不同的文件系统。它支持多种文件系统类型,包括本地磁盘、FTP、HTTP、ZIP、RAR等。JMX模块使得...
在标签部分,“JAVA”指明了与Java语言相关的技术,“JMX”则是我们讨论的核心,两者结合意味着这份资料专注于Java平台上的管理扩展技术。 虽然压缩包的文件名列表只给出了“新建文件夹”,这通常表示压缩包内可能...
压缩包中的“一起分享 一起成长 - goCom - SOA中国第一社区.htm”可能是某个社区讨论JMX的网页,其中可能包含了一些讨论、示例代码或者用户的经验分享。“新建 文本文档.txt”可能是一份简单的文本教程,介绍JMX的...
- **监控JMS资源**:讨论了如何使用JMX监控JMS中的各种资源,如队列、主题等。 - **性能调优**:提供了关于如何使用JMX进行JMS系统性能调优的指导和建议。 - **高级主题**:涉及一些高级主题,如故障转移、负载均衡...
6. **最佳实践**:博主可能分享了一些关于如何有效利用JMX通知,避免过度通知导致性能问题,以及安全考虑的最佳实践。 7. **工具支持**:提到了Java标准工具(如JConsole、VisualVM)和其他第三方工具,如何利用...
JMX规范还讨论了如何在不同的Java虚拟机(JVM)实例之间进行通信,以及如何在不同的平台和应用程序之间使用JMX技术进行统一的管理和监控。规范中还定义了测试和兼容性工具包(TCK),用于确保第三方的实现符合JMX...
书中还深入讨论了使用JMX进行性能监控和故障诊断的方法,包括使用内置的MBeans(如内存、线程和类加载器MBeans)以及创建自定义MBeans来收集和分析系统数据。此外,JMX的工具和API如jconsole、jvisualvm等也是书中...
本章节重点讨论了JMX代理服务中的高级MBean加载机制,特别是如何从远程位置动态加载类文件创建MBeans。 在开发长时间运行的Java应用程序时,经常会遇到需要重启应用以更新CLASSPATH的情况。对于正在运行的JMX代理,...
在深入探讨JMX(Java ...总结,JMX IN ACTION的第八章深入讨论了MBean服务器及其查询机制,这对于开发和管理复杂的Java系统至关重要。掌握这些知识可以帮助你有效地组织和管理MBeans,提高系统的可管理性和可维护性。