1. 程式人生 > >JMX之通過RMI方式連線JMX Server

JMX之通過RMI方式連線JMX Server

除了可以在HTML中管理MBean之外,我們還可以通過程式來連線JMX管理MBean。這就需要用到了JMX的Connectior,JMX提供了兩種Connector:RMI Connector和JMXMP Connector(JMX message protocol Connector)。下面介紹RMI Connector。

首先還是要建立MBean介面和實現

package com.jmx.client;

public interface HelloMBean {
	public String getName();
	
	public void setName(String name);
	
	public void helloWorld();
	
	public void helloWorld(String name);
	
	public String getTelephone();
	
}

package com.jmx.client;

public interface HelloMBean {
	public String getName();
	
	public void setName(String name);
	
	public void helloWorld();
	
	public void helloWorld(String name);
	
	public String getTelephone();
	
}

建立JMXServer和JMXConnectorServer(通過RMI註冊URL提供客戶端連線)
package com.jmx.client;

import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.net.MalformedURLException;
import java.rmi.registry.LocateRegistry;

import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;

import com.sun.jdmk.comm.HtmlAdaptorServer;

public class HelloAgent {
	public static void main(String[] args) throws MalformedObjectNameException, NullPointerException, InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException {
		
		//create mbean server
		MBeanServer server = ManagementFactory.getPlatformMBeanServer();
		
		//create object name
		ObjectName helloName = new ObjectName("jmxBean:name=hello");
		
		//create mbean and register mbean
		server.registerMBean(new Hello(), helloName);
		
		//create adaptor, adaptor is just a form as show mbean. It has no relation to specific mbean.
		HtmlAdaptorServer adaptor  = new HtmlAdaptorServer();
		//create adaptor name
		ObjectName adaptorName = new ObjectName("jmxAdaptor:name=adaptor,port=5050");
		//register adaptor and adaptor name
		server.registerMBean(adaptor, adaptorName);
		
		adaptor.setPort(9999);
		adaptor.start();
		System.out.println("....................server start....................");
		
		//JMXConnectorServer service 
		try {
			//這句話非常重要,不能缺少!註冊一個埠,繫結url後,客戶端就可以使用rmi通過url方式來連線JMXConnectorServer
			LocateRegistry.createRegistry(8888);
			JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:8888/server");
			JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, server);
			System.out.println("....................begin rmi start.....");
			cs.start();
			System.out.println("....................rmi start....."); 
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}   
	}
}

這裡的8888(預設為1099)是通訊埠或者查詢埠,服務端在createRegistry時實際上會new ServerSocket(8888),客戶端的socket通過與埠號為8888的服務端埠互聯lookup到server物件。客戶端獲取到的server物件在和服務端的sketon物件進行通訊時實際上也會建立socket連線,資料傳輸時的ServerSocket也需要一個埠(不同於通訊埠),稱之為資料埠。

建立客戶端程式碼遠端連線JMXConnectorServer操作MBean
package com.jmx.client;

import java.util.Iterator;
import java.util.Set;

import javax.management.Attribute;
import javax.management.MBeanInfo;
import javax.management.MBeanServerConnection;
import javax.management.MBeanServerInvocationHandler;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

import com.jmx.demo.HelloMBean;

public class Client {   
	
	public static void main(String[] args) throws Exception {
		
		//connect JMX
		JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:8888/server");
		JMXConnector jmxc = JMXConnectorFactory.connect(url,null);
		MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();     
		ObjectName mbeanName = new ObjectName("jmxBean:name=hello");   
		
		//print domains
		System.out.println("Domains:---------------");
		String domains[] = mbsc.getDomains();
		for (int i = 0; i < domains.length; i++) {       
			System.out.println("\tDomain[" + i +"] = " + domains[i]);    
		}   
		//MBean count
		System.out.println("MBean count = " + mbsc.getMBeanCount());    
		
		//process attribute
		mbsc.setAttribute(mbeanName, new Attribute("Name", "new value"));//set value
		System.out.println("Name = " + mbsc.getAttribute(mbeanName, "Name"));//get value
		
		//invoke via proxy
		HelloMBean proxy = (HelloMBean) MBeanServerInvocationHandler.newProxyInstance(mbsc, mbeanName, HelloMBean.class, false);        
		proxy.helloWorld();
		proxy.helloWorld("I'll connect to JMX Server via client.");   
		
		//invoke via rmi
		mbsc.invoke(mbeanName, "helloWorld", null, null);         
		mbsc.invoke(mbeanName, "helloWorld", new Object[] { "I'll connect to JMX Server via client2." }, new String[] { String.class.getName() });   
		
		//get mbean information
		MBeanInfo info = mbsc.getMBeanInfo(mbeanName);         
		System.out.println("Hello Class:" + info.getClassName());      
		System.out.println("Hello Attriber:" + info.getAttributes()[0].getName());     
		System.out.println("Hello Operation:" + info.getOperations()[0].getName());   
		
		//ObjectName of MBean
		System.out.println("all ObjectName:---------------");        
		Set set = mbsc.queryMBeans(null, null);
		for (Iterator it = set.iterator(); it.hasNext();) {
			ObjectInstance oi = (ObjectInstance)it.next();        
			System.out.println("\t" + oi.getObjectName());        
		}
		jmxc.close();     
	}    
}