天天看點

JMX學習筆記(四) JMX RMI

連接配接器概念:

JMX規範定義了連接配接器的概念(Connectors),連接配接器位于JMX的3層構架中的分布式服務層。連接配接器負責建立MBean伺服器和管理應用之間的通信。連接配接器由一個駐留在代理層的連接配接器伺服器(connector server)和管理應用的連接配接器用戶端(connector client)構成。連接配接器服務端(connector server)連接配接到MBean伺服器并監聽來自用戶端(connector client)的請求。一個connector client負責與connector server建立連接配接。connnector client通常與connector server在不同的JVM裡并且通常運作在不同的機器上。

1.連接配接器類型(Connector type)

connnector client通過給定協定與connector server建立連接配接,遠端通路MBean伺服器。JMX API允許使用不同類型的連接配接器來連接配接MBean伺服器。

* JMX API定義了一個标準連接配接器 - RMI Connector,它支援通過RMI協定遠端通路一個MBeanServer

* JMX API定義了一個可選的連接配接器 - JMXMP Connector.它實作了JMXMP協定(JMX Message Protocol).作為一個可選連接配接器,它不內建在JavaSE平台中,若需要,從Sun官方      下載下傳jar

* 使用者自定義連接配接器協定

2.連接配接器伺服器位址

通常,一個connector server有一個位址,由類JMXServiceURL表示,這個類的執行個體是不可變的。使用不同的連接配接器,會有不同的JMXServiceURL編寫方式。

格式看起來如下:

service:jmx:protocol:sap

說明:

service:jmx: 這個是JMX URL的标準字首,所有的JMX URL都必須以該字元串開頭。

protocol是指定連接配接連接配接器伺服器(connector server)的傳輸協定

方括号中的部分為可選部分

sap是連接配接器伺服器的位址,sap的文法格式://[host[:port]][url-path]

host表示主機名,port是十進制的端口号

host和port可以省略,但沒有host時,不能出現port

url-path 開始于一個"/"符号

參考JMX API : http://docs.oracle.com/javase/8/docs/api/index.html?javax/management/remote/rmi/package-summary.html

參考:http://www.l99.com/EditText_view.action?textId=480750

3. RMI連接配接器

JMX API定義了一個标準連接配接器 - RMI Connector,它支援通過RMI遠端通路一個MBeanServer

RMI連接配接器伺服器的位址示例如下:

service:jmx:rmi://localhost:1099/jndi/rmi://localhost:8899/myname

說明:

在這個JMXServiceURL中,第一個rmi指的是rmi連接配接器,表示用連接配接器使用RMI傳輸協定,第二個rmi指定RMI注冊RMI連服務接器存儲存根

localhost:1099: 這個是connector server的IP和端口,該部分是一個可選項,可以被省略掉。如果省略的話,則connector server會随機任意選擇一個可用的端口

/jndi/rmi://localhost:8899/myname: 這個是connector server的路徑,表示Connector server的stud是使用JNDI API綁定在rmi://localhost:8899/myname這個位址上

建立一個RMI connector server

通常是提供一個RMI connector server的連接配接器位址,用JMXConnectorServerFactory.newJMXConnectorServer方法來建立RMI connector cerver

參考JMX API:http://docs.oracle.com/javase/8/docs/api/index.html?javax/management/remote/rmi/package-summary.html

下面是使用RMI連接配接器遠端管理程式的例子:

Step 1.MBean接口定義

package com.jmx.demo9;

import java.io.Serializable;

public interface HelloMBean extends Serializable {
	public void setName(String name);

	public String getName();

	public void sayHello();

}
           

Step 2.MBean接口實作類

package com.jmx.demo9;

import java.io.Serializable;

public class Hello implements HelloMBean, Serializable {

	private String name;

	public synchronized void setName(String name) {
		this.name = name;
	}

	public synchronized String getName() {
		return name;
	}

	public synchronized void sayHello() {
		System.out.println("Hello," + name);
	}

}
           

Step 3.服務端

package com.jmx.demo9;

import java.rmi.registry.LocateRegistry;
import java.util.HashMap;

import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.remote.JMXAuthenticator;
import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;
import javax.security.auth.Subject;

public class JMXAgent {
	/**
	 * @param args
	 *            the command line arguments
	 */
	public static void main(String[] args) throws Exception {
		System.out.println("--------------JMX Agent----------- ");
		LocateRegistry.createRegistry(1099);
		MBeanServer server = MBeanServerFactory.createMBeanServer();
		ObjectName helloName = new ObjectName("com.jmx.demo9:name=Hello");
		Hello hello = new Hello();
		HashMap<String, Object> prop = new HashMap<String, Object>();
		prop.put(JMXConnectorServer.AUTHENTICATOR, new JMXAuthenticator() {
			public Subject authenticate(Object credentials) {
				if (credentials instanceof String) {
					if (credentials.equals("Hello")) {
						return new Subject();
					}
				}
				throw new SecurityException("not authicated");
			}
		});
		JMXConnectorServer cserver = JMXConnectorServerFactory
				.newJMXConnectorServer(new JMXServiceURL(
						"service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi"),
						prop, server);
		cserver.start();
		server.registerMBean(hello, helloName);
		for (ObjectInstance object : server.queryMBeans(null, null)) {
			System.out.println(object.getObjectName());
		}
		System.out.println(hello);
		System.out.println("start.....");
		System.out.println("\n");
	}
}
           

note:ObjectName對象辨別符命名規則參考JMX API:http://docs.oracle.com/javase/8/docs/api/javax/management/ObjectName.html

Step 4.用戶端(管理應用程式)

package com.jmx.demo9;

import java.util.HashMap;

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;

public class Client {

	public static void main(String[] args) throws Exception {
		
		HashMap<String, Object> prop = new HashMap<String, Object>();
		prop.put(JMXConnector.CREDENTIALS, "Hello");
		JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi");
		JMXConnector conn = JMXConnectorFactory.connect(url, prop);
		MBeanServerConnection mbsc = conn.getMBeanServerConnection();
		ObjectName mbeanName = new ObjectName("com.jmx.demo9:name=Hello");
		HelloMBean hello = JMX.newMBeanProxy(mbsc, mbeanName,HelloMBean.class);
		hello.setName("World!");
		hello.sayHello();

	}
}
           

測試結果:

先啟動JMXAgent,在啟動Client

--------------JMX Agent----------- 
JMImplementation:type=MBeanServerDelegate
com.jmx.demo9:name=Hello
[email protected]
start.....


Hello,world
           
JMX