继续之前的,之前介绍了MBean server (http://90haofang-163-com.iteye.com/blog/1901416),这次主要简述如果使用JMX技术管理MBean,执行远程操作。通过RMI 作为connectors访问MBeans。这块需要实现服务端和客户端。
首先编写服务端:
1.创建MBean接口类SimpleStandardMBean
package git.git.tudou.manage.jmx.test.connectors;
/**
* Date: 13-7-9
* Time: 下午4:06
*/
public interface SimpleStandardMBean {
//获取当前state 值
public String getState();
//修改state
public void setState(String state);
//获取状态改变次数
public int getNuberChanges();
//重置state和计数器 为初始值
public void reset();
}
然后编写MBean实现类SimpleStandard,名字必须是MBean的前缀,不然创建的MBean会出现问题。
package git.git.tudou.manage.jmx.test.connectors;
import javax.management.AttributeChangeNotification;
import javax.management.NotificationBroadcasterSupport;
import java.util.Date;
/**
* standard MBean支持notification广播功能
* Date: 13-7-9
* Time: 下午4:05
*/
public class SimpleStandard extends NotificationBroadcasterSupport implements SimpleStandardMBean{
private String state = "initial stae";
private int nuberChanges=0;
private int nbReset = 0;
public String getState() {
return this.state;
}
public void setState(String state) {
this.state =state;
//状态次数加1
this.nuberChanges++;
}
public int getNuberChanges() {
return this.nuberChanges;
}
public int getNbReset(){
return this.nbReset;
}
public void reset() {
state = "init state" ;
this.nuberChanges = 0;
nbReset++;
/**
* 属性变更通知
* 参数说明
* p1:指示通知的来源 在这里就是Hello MBean,用this替代
* p2: 通知消息的序列号
* p3:时间戳
* p4:通知的内容
* p5:变更的属性名
* p6:变更属性的数据类型
* p7: 属性的原值
* p8:属性的新值
*/
AttributeChangeNotification acn = new AttributeChangeNotification(
this,nbReset,new Date().getTime(),"状态改变次数重置 ,state重置","Nbchanges","int",nuberChanges,0);
sendNotification(acn);
}
}
该类继承了NotificationBroadcasterSupport ,实现通知功能在reset方法中发送了一个通知,说明nbchanges被重置,后面在客户端实现一个监听器,来接受通知。
服务端类Server
package git.git.tudou.manage.jmx.test.connectors;
import javax.management.*;
import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;
import java.rmi.registry.LocateRegistry;
import java.util.Scanner;
/**
* MBean server
* encode gbk
* Date: 13-7-9
* Time: 下午2:57
*/
public class Server {
public static void main(String args[]){
try{
Scanner sc = new Scanner(System.in);
LocateRegistry.createRegistry(9999); //必须加上这句 不然就报错了
//创建一个MBean server
MBeanServer mBeanServer = MBeanServerFactory.createMBeanServer();
//停顿一下
sc.nextInt();
//获得mBeanServer 默认域
String domain = mBeanServer.getDefaultDomain();
System.out.println("mBeanServer defualt domain:"+domain);
sc.nextInt();
//创建一个并且注册一个 SimpleStandard MBean
String mbeanClassName = "git.git.tudou.manage.jmx.test.connectors.SimpleStandard";
String mbeanObjectNameStr = domain+":type="+mbeanClassName+",name=1";
//在MBean server创建一个bean
ObjectName mBeanObjectName = createSimpleMBean(mBeanServer,mbeanClassName,mbeanObjectNameStr);
//输出MBean info
printMBeanInfo(mBeanServer,mBeanObjectName,mbeanObjectNameStr);
sc.nextInt();
//通过MBean server管理MBean 类
manageSimpleMBean(mBeanServer,mBeanObjectName,mbeanClassName);
sc.nextInt();
//创建RMI server 工程应用程序调用
JMXServiceURL url = new JMXServiceURL(//url 绑定9999端口,这个可以自定义
"service:jmx:rmi:///jndi/rmi://10.12.145.22:9999/server");
//通过JMXConnectorServerFactory工厂 创建一个RMI连接实例
JMXConnectorServer connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(url,null,mBeanServer);
//启动RMI连接服务器
connectorServer.start();
System.out.println("RMI 服务已经启动..等待接受请求.");
sc.nextInt();
System.out.println("RMI服务关闭..");
connectorServer.stop();
}catch (Exception e){
System.out.println("创建mbean server 异常"+e);
}
}
//管理simpleMBean类
public static void manageSimpleMBean(MBeanServer mbs,ObjectName mbeanObjectName,String mbeanClassName){
try{
//打印最开始的属性值
printSimpleAttributes(mbs,mbeanObjectName);
System.out.println("--------------------------------");
System.out.println("修改state值为new state");
Attribute attribute = new Attribute("State","new state");
mbs.setAttribute(mbeanObjectName,attribute);
System.out.println("--------------------------------");
System.out.println("修改后的属性值:");
printSimpleAttributes(mbs,mbeanObjectName);
//调用reset方法
mbs.invoke(mbeanObjectName,"reset",null,null);
System.out.println("重置后所有属性值:");
printSimpleAttributes(mbs,mbeanObjectName);
}catch (Exception e){
System.out.println("变更Simple Bean异常"+e);
}
}
/**
* 答应出MBean 的属性
* @param mbs
* @param mbeanObjectName
*/
public static void printSimpleAttributes(MBeanServer mbs,ObjectName mbeanObjectName){
System.out.println("属性集合:");
try{
System.out.println("--------------------------------");
System.out.println("SimpleMBean 属性值:");
String state =(String)mbs.getAttribute(mbeanObjectName,"State");
System.out.println("\tstate:"+state);
int nuberChanges = (Integer)mbs.getAttribute(mbeanObjectName,"NuberChanges");
System.out.println("\tnuberChanges:"+nuberChanges);
}catch (Exception e){
System.out.println("获取mbean属性异常"+e);
}
}
/**
* 打印MBean 信息
* @param mbs
* @param mbeanObjectName
* @param mbeanClassName
*/
public static void printMBeanInfo(MBeanServer mbs,ObjectName mbeanObjectName,String mbeanClassName){
MBeanInfo info = null;
try{
info = mbs.getMBeanInfo(mbeanObjectName);
}catch (Exception e){
e.printStackTrace();
System.out.println("获取"+mbeanClassName+"MBeanInfo 失败");
}
System.out.println("-------------------------------------------");
System.out.println("类名:\t"+info.getClassName());
System.out.println("类描述:\t"+info.getDescription());
System.out.println("-------------------------------------------");
System.out.println("属性:");
MBeanAttributeInfo[] attributeInfos = info.getAttributes();
for(MBeanAttributeInfo ainfo:attributeInfos){
System.out.println("属性名:\t"+ainfo.getName());
System.out.println("属性描述:\t"+ainfo.getDescription());
System.out.println("属性数据类型\t"+ainfo.getType());
System.out.println("属性是否可读\t"+ainfo.isReadable());
System.out.println("属性是否可写\t"+ainfo.isWritable());
}
System.out.println("-------------------------------------------");
System.out.println("构造方法:");
MBeanConstructorInfo[] constructorInfos = info.getConstructors();
for(MBeanConstructorInfo cinfo:constructorInfos){
System.out.println("方法名:\t"+cinfo.getName());
System.out.println("方法描述:"+cinfo.getDescription());
System.out.println("参数个数:\t"+cinfo.getSignature().length);
}
System.out.println("-------------------------------------------");
System.out.println("方法:");
MBeanOperationInfo[] operationInfos= info.getOperations();
for(MBeanConstructorInfo oinfo:constructorInfos){
System.out.println("方法名:\t"+oinfo.getName());
System.out.println("方法描述:"+oinfo.getDescription());
System.out.println("参数个数:\t"+oinfo.getSignature().length);
}
System.out.println("-------------------------------------------");
System.out.println("通知:");
MBeanNotificationInfo[] notificationInfos = info.getNotifications();
for(MBeanNotificationInfo ninfo:notificationInfos){
System.out.println("通知名:\t"+ninfo.getName());
System.out.println("通知描述:"+ninfo.getDescription());
String notificationType[] = ninfo.getNotifTypes();
for(int i=0;i<notificationType.length;i++){
System.out.println("type \t"+notificationType[i]);
}
}
}
public static ObjectName createSimpleMBean(MBeanServer mbs,String mbeanClassName,String mbeanObjectNameStr){
try{
System.out.println("创建一个MBean "+mbeanClassName+"并在server 注册");
ObjectName mbeanObjectName = ObjectName.getInstance(mbeanObjectNameStr);
//MBean server创建一个bean
mbs.createMBean(mbeanClassName,mbeanObjectName);
return mbeanObjectName;
}catch (Exception e){
e.printStackTrace();
System.exit(1);
}
return null;
}
}
这里类首先创建一个MBserver.然后通过RMI发布出去。供远程应用程序调用,要注意的是
LocateRegistry.createRegistry(9999); //这个很重要。不然直接无发绑定端口号,10.12.145.22是我的server运行的ip地址,应该替换为自己的server运行的ip地址。
创建mbean server 异常java.io.IOException: Cannot bind to URL [rmi://10.12.145.22:9999/server]: javax.naming.ServiceUnavailableException [Root exception is java.rmi.ConnectException: Connection refused to host: 10.12.145.22; nested exception is:
java.net.ConnectException: Connection refused: connect]
Disconnected from the target VM, address: '127.0.0.1:51094', transport: 'socket'
编写好服务端后,不着急写客户端首先可以用jconsole连接下这个服务地址 service:jmx:rmi:///jndi/rmi://10.12.145.22:9999/server 查看MBean,如图
下图是我执行了操作reset,一共执行了2次,所以收到了两个通知,通知的发送定义在SimpleStandardMBean.reset方法中。
接下自己编写客户端来管理MBean,通过RMI连接到MBserver,首先创建一个客户端监听器ClientListener,用来处理来自MBserver的通知
package git.git.tudou.manage.jmx.test.connectors;
import javax.management.Notification;
import javax.management.NotificationListener;
/**
* 客户端监听通知监听器
* Date: 13-7-9
* Time: 下午6:54
*/
public class ClientListener implements NotificationListener {
public void handleNotification(Notification notification, Object handback) {
System.out.println("来自MBean server通知:"+notification.getMessage());
}
}
ClientListener实现NotificationListener接口,实现handleNotification,用来处理来自客户端的通知。
接下来编写客户端Cient类
package git.git.tudou.manage.jmx.test.connectors;
import javax.management.Attribute;
import javax.management.JMX;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Set;
/**
* 创建一个RMI连接客户端
* Date: 13-7-9
* Time: 下午6:56
*/
public class Client {
public static void main(String[] args) {
try{
Scanner sc = new Scanner(System.in);
//通过rmi连接远程MBean
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://10.12.145.22:9999/server");
//获得远程JMX连接
JMXConnector jmxConnector = JMXConnectorFactory.connect(url,null);
ClientListener listener = new ClientListener();
//获得MBserverConnection
MBeanServerConnection mBeanServerConnection = jmxConnector.getMBeanServerConnection();
sc.nextInt();
System.out.println("domain:");
//获Mbean server所有连接
String domains[] = mBeanServerConnection.getDomains();
for(int i=0;i<domains.length;i++){
System.out.println("domains["+i+"]="+domains[i]);
}
sc.nextInt();
String domain=mBeanServerConnection.getDefaultDomain();
String mbeanObjectNameStr = domain+":type=SimpleStandard,name=2";
//新建一个ObjectName实例
ObjectName mbeanObjectName = ObjectName.getInstance(mbeanObjectNameStr);
//创建一个MBean
mBeanServerConnection.createMBean("git.git.tudou.manage.jmx.test.connectors.SimpleStandard",mbeanObjectName,null,null);
sc.nextInt();
//获取所有的Object名字
Set names = mBeanServerConnection.queryNames(null, null);
for (Iterator i= names.iterator();i.hasNext();){
System.out.println("ObjectName"+(ObjectName)i.next());
}
sc.nextInt();
//管理MBean 首先变更属性
System.out.println("state:"+(String)mBeanServerConnection.getAttribute(mbeanObjectName,"State"));
mBeanServerConnection.setAttribute(mbeanObjectName, new Attribute("State", "new state2"));
System.out.println("修改后 state:"+(String)mBeanServerConnection.getAttribute(mbeanObjectName,"State"));
//方式二 直接通过MXBean代理
/**
* p1 MBean server连接
* p2 MBean name
* p3 接口类
* p4 标记是否是NotificationBroadSupport
*/
SimpleStandardMBean proxy = JMX.newMXBeanProxy(mBeanServerConnection,mbeanObjectName,SimpleStandardMBean.class,true);
System.out.println("state 使用proxy:"+proxy.getState());
//添加Notification监听器
System.out.println("添加Notification监听器");
mBeanServerConnection.addNotificationListener(mbeanObjectName,listener,null,null);
//mBeanServerConnection 调用SimpleStandard reset方法
mBeanServerConnection.invoke(mbeanObjectName,"reset",null,null);
// proxy 调用reset方法
System.out.println("proxy 调用reset方法");
proxy.reset();
sc.nextInt();
Thread.sleep(2000);
System.out.println("关闭连接。。。。");
sc.nextInt();
jmxConnector.close();
}catch (Exception e){
System.out.println("连接远程rmi异常,无法获得MBserver 连接"+e);
}
}
}
改客户端类首先连接RMIserver 获得一个连接器,从连接器获得MBean server连接mBeanServerConnection,然后通过这个连接来管理远程MBean,可以通过它改变MBean属性,调用其方法
代码里面用两种方式获得MBean,一种是直接通过MBean创建,一种是proxy模式。通过MBean接口实例,调用MBean方法或者修改它的属性。
然后启动服务端,控制台输出:
1
mBeanServer defualt domain:DefaultDomain
1
创建一个MBean git.git.tudou.manage.jmx.test.connectors.SimpleStandard并在server 注册
-------------------------------------------
类名: git.git.tudou.manage.jmx.test.connectors.SimpleStandard
类描述: Information on the management interface of the MBean
-------------------------------------------
属性:
属性名: State
属性描述: Attribute exposed for management
属性数据类型 java.lang.String
属性是否可读 true
属性是否可写 true
属性名: NuberChanges
属性描述: Attribute exposed for management
属性数据类型 int
属性是否可读 true
属性是否可写 false
-------------------------------------------
构造方法:
方法名: git.git.tudou.manage.jmx.test.connectors.SimpleStandard
方法描述:Public constructor of the MBean
参数个数: 0
-------------------------------------------
方法:
方法名: git.git.tudou.manage.jmx.test.connectors.SimpleStandard
方法描述:Public constructor of the MBean
参数个数: 0
-------------------------------------------
通知:
1
属性集合:
--------------------------------
SimpleMBean 属性值:
state:initial stae
nuberChanges:0
--------------------------------
修改state值为new state
--------------------------------
修改后的属性值:
属性集合:
--------------------------------
SimpleMBean 属性值:
state:new state
nuberChanges:1
重置后所有属性值:
属性集合:
--------------------------------
SimpleMBean 属性值:
state:init state
nuberChanges:0
1
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
RMI 服务已经启动..等待接受请求.
执行客户端main方法,输出:
1
domain:
domains[0]=JMImplementation
domains[1]=DefaultDomain
1
1
ObjectNameDefaultDomain:type=SimpleStandard,name=2
ObjectNameDefaultDomain:type=git.git.tudou.manage.jmx.test.connectors.SimpleStandard,name=1
ObjectNameJMImplementation:type=MBeanServerDelegate
1
state:initial stae
修改后 state:new state2
state 使用proxy:new state2
添加Notification监听器
proxy 调用reset方法
来自MBean server通知:状态改变次数重置 ,state重置
来自MBean server通知:状态改变次数重置 ,state重置
可以最后两行客户端已经收到通话,说明客户端和服务进行了交互,能够通过RMI连接远程的MBean用于应用程序的管理,具体的业务实现类似,回头再写一个和spring整合的JMX。
- 大小: 141.6 KB
- 大小: 92.9 KB
- 大小: 141.6 KB
分享到:
相关推荐
3. JMX Connectors:JMX连接器允许客户端与MBean服务器通信,支持RMI、HTTP、HTTPS等多种协议。 4. Notifications:MBeans可以通过发送通知来通告系统状态的变化,客户端可以订阅这些通知。 5. Attributes, ...
- **JMX Connectors**:提供了客户端与MBean Server之间的通信协议,如RMI/JRMP和JMXMP。 - **JMX URL**:用于指定连接到MBean Server的格式,如`service:jmx:rmi:///jndi/rmi://hostname:port/jmxrmi`。 总的来说...
- **JMX Connectors**: 为客户端提供连接到JMX代理的接口,允许远程管理。 - **Security**: 支持JMX连接的安全性,包括认证和授权机制。 这两个jar文件通常一起使用,以实现完整的JMX远程管理功能。在部署Java...
这个版本可能包含了更新的连接器(Connectors)和协议支持,提高了安全性,增强了稳定性,并修复了一些已知问题。同样,它也包括了API库、示例和文档。 3. **jmx-1_1-mr-spec.zip**:这是JMX 1.1 Management ...
5. **Connectors**:JMX连接器允许远程访问MBean服务器,这样管理员就可以通过网络来监控和管理远程系统。 6. **Adapters**:适配器允许JMX与其他管理系统(如SNMP、WMI)集成,扩展了JMX的监控范围。 使用JMX,...
【标题】"jakarta-tomcat-connectors-1.2.15-src.zip" 是一个包含Apache Tomcat连接器源代码的压缩包,主要用于帮助开发者深入理解Tomcat的工作原理,并进行自定义或扩展。 【描述】提到的"jakarta_tomcat_...
JMX的核心概念包括MBeans(Managed Beans)、代理(Agents)、服务提供者接口(Service Provider Interfaces,SPIs)和连接器(Connectors)。MBeans是Java对象,代表可管理的资源或服务,它们提供了暴露管理属性和...
4. **JMX Connectors**: 它们提供了访问MBean Server的通道,允许远程管理应用或JVM。 **JMX在JVM中的应用** 1. **JVM监控**: JMX可以通过MBeans提供JVM的性能指标,如内存使用情况、线程状态、类加载统计等。 2....
JMX的核心概念包括MBeans(Managed Beans)、Servers、Agents以及Connectors,它们共同构成了一个灵活的管理架构。 1. **JMX简介** JMX的主要作用是让开发者能够创建和注册可管理的对象,即MBeans,它们代表了应用...
5. **JMX Connectors**:它们是MBean Server和管理客户端之间的通信桥梁。JMX Connectors定义了多种协议,如RMI、HTTP/HTTPS等,以便于远程访问和管理。 6. **Adapters**:适配器允许JMX与非Java系统的交互,例如,...
除此之外,jmxtools.jar还可能包含其他辅助类,帮助开发者在代码中实现JMX功能,如连接器(connectors)和其他管理工具。 描述中提到的"2个jar包maven仓库中缺少这个jar包"可能意味着在进行某些Java项目开发或构建...
学习JMX,需要理解其基本概念,熟悉MBean的创建和注册,掌握如何使用JMX Connectors进行远程监控,以及如何利用JMX进行应用性能调优。对于开发者而言,JMX是提高应用可维护性和可管理性的重要工具。通过深入学习和...
3. JMX Connectors:JMX Connectors提供了MBean Server与外部世界的通信桥梁。它们定义了标准的协议和API,使得管理工具能够远程连接到MBean Server进行管理操作。 4. 管理工具:JMX支持多种类型的管理工具,包括...
当你在应用程序中使用JMX特性时,`jmxri.jar` 提供了运行JMX代理(MBeans)和连接器(Connectors)所需的类和接口。它包含了服务器端的实现,比如MBeanServer,以及远程访问JMX代理的基础设施。 2. **jmxremote.jar...
4. **管理接口暴露**:可能通过JMX的RMI或者JMX Connectors暴露MBeanServer,使得远程客户端能够访问。 5. **客户端工具**:使用JConsole、VisualVM或其他支持JMX的工具,连接到MBeanServer,查看和操作MBean。 ...
5. **JMX Connectors**:提供客户端和MBean服务器之间的通信机制。JMX Connectors有多种协议实现,如RMI、HTTP/HTTPS、JNDI等,使得远程管理成为可能。 在实际应用中,JMX常用于监控和管理Java应用程序的性能、配置...
RMI允许跨网络调用对象方法,而JMX Connectors则是JMX和外部世界的桥梁,支持多种协议如JMX Remote Protocol,允许客户端通过网络连接到MBeanServer。 五、监控CPU利用率 在JMX中,可以使用MBeans获取操作系统级别...
- 连接器(Connectors):提供与外界通信的桥梁,支持远程访问MBean服务器。 - 协议适配器(Protocol Adaptors):将特定的协议转换为JMX协议,使得基于不同协议的系统可以访问JMX管理系统。 - 代理层(Proxy Layer...
**Protocol Adapters and Connectors** 用于JMX Agent与其他系统通信。适配器(Adapter)处理特定协议(如HTTP、SNMP),而连接器(Connector)则在Agent端和客户端都有相应组件,处理请求和响应。例如,RMI ...