`
ginge
  • 浏览: 211892 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

RMI Tips

阅读更多

I’ve come across a lot of business logics in my company that take advantage of the RMI remoting technology. It’s said that the performance of RMI is not only poor, but also is too heavy. However some serious articles and benchmark tests argue that it’s not bad. And I also did some simple performance tests among some remoting technologies, and the result reveals RMI is the best at least in the LAN.

 

The following is a summary about the most important skills that can promote the speed of RMI as well as a personal RMI debugging logic.

 Externalizable instead of Serializable

Default Serialization is slow and we should use the Externalizable interface to transfer only those necessary properties and fields over the network to reduce the network traffic and response time.

 

Here’s an example:

 

public class SerializedClass implements Serializable

    {

        private String aString;

        private int anIntA;

        private int anIntB;

        private float[] floatArray;

        private Dimension dimensionA;

        private Dimension dimensionB;

        // No more code related to serialization!

             :

             :

    public class ExternalizedClass implements Externalizable

    {

        private String aString;

        private int anIntA;

        private int anIntB;

        private float[] floatArray;

        private Dimension dimensionA;

        private Dimension dimensionB;

      

        public void writeExternal(ObjectOutput out) throws IOException

        {

            out.writeObject(aString);

            out.writeInt(anIntA);

            out.writeInt(anIntB);

            out.writeObject(floatArray);

            out.writeObject(dimensionA);

            out.writeObject(dimensionB);

        }

        public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException

        {

            aString = (String)in.readObject();

            anIntA = in.readInt();

            anIntB = in.readInt();

            floatArray = (float[])in.readObject();

            dimensionA = (Dimension)in.readObject();

            dimensionB = (Dimension)in.readObject();

        }

        // Etc.

 

 

The above code snippet is quoted from Accelerate your RMI programming. If you’re interesting in the benefit that gained from this method, I suggest you read the article.

Use null for default objects

Java would not transfer the null value over the network and this could also make your object compact.

 

Use the transient key word

If you are really sure about a property that is not valuable for you remote user, then make it a local property with the transient key word. Use the transient keyword to define fields to avoid having those fields serialized. Examine serialized objects to determine which fields do not need to be serialized for the application to work.

 

 

Specify a specific IP address to bind the remote service

We need to bind our remote service to a specific IP address from time to time if there are multiple network interfaces on a server. And as now we are more often using Spring to expose our remote service, I will show the Spring way to specify the IP address to bind to at run time.

<bean id="xxxRMIServiceExporter"
		class="org.springframework.remoting.rmi.RmiServiceExporter">
		<property name="serviceName">
		    <value>BillingRemoteService</value>
		</property>
		<property name="service">
		    <ref bean="billingRMIService"/>
		</property>
		<property name="serviceInterface">
		    <value>com.xxx.xxx.BillingRemoteService</value>
		</property>
		<property name="registryPort">
		    <value>1199</value>
		</property>
		<property name="registryHost">
		  <value>192.168.21.161</value>
		</property>
	</bean>

 

 

 

How to debug

We’ve been stuck in the RMI in our products’ previous development version and have limited knowledge about RMI, and hereafter we could only fix some problems by our experience. We want to know how many remote services have been registered, want to know if a particular service is up and running and list the methods on a service, etc.

 

Here’s the interface:

 

package com.bee.fw.rmi;
import java.lang.reflect.InvocationTargetException;
import java.rmi.Remote;
/**
 * @author Ginge
 */
public interface RmiServiceManager {
	/**
	 * List all the registered Remote Services bound to the port at the host
	 * @param host
	 * @param port
	 * @return
	 */
	String [] listRemoteObjects(String host, int port);
	
	/**
	 * Find the registered Remote Service bound to the port at the host
	 * @param host
	 * @param port
	 * @param remoteObject
	 * @return
	 * @throws RemoteObjectNotFoundException
	 */
	Remote findRemoteObjects(String host, int port, String remoteObject) throws RemoteObjectNotFoundException;
	
	/**
	 * Invoke the remote method on the remote Object
	 * @param host
	 * @param port
	 * @param remoteObject
	 * @param methodName
	 * @param args
	 * @return
	 * @throws RemoteObjectNotFoundException
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 * @throws NoSuchMethodException
	 */
	Object invokeRemoteMethod(String host, int port, String remoteObject, String methodName, Object ...args)
	throws RemoteObjectNotFoundException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, NoSuchMethodException ;
}

 

 

 

And the implementation, it requires at least Spring 2.0.5:

package com.bee.fw.rmi;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.rmi.AccessException;
import java.rmi.NotBoundException;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.SimpleTypeConverter;
/**
 * 
 * @author Ginge
 *
 */
public class RmiServiceManagerImpl implements RmiServiceManager {

	private Log log = LogFactory.getLog(this.getClass());
	
	private SimpleTypeConverter simpleTypeConverter = new SimpleTypeConverter();

	private Registry getRegistry(String host, int port) {

		Registry registry = null;
		try {
			if(log.isDebugEnabled())
			{
				log.debug("Locating registry at host["+host+"] on port["+port+"]");
			}
			registry = LocateRegistry.getRegistry(host, port);
		} catch (RemoteException e) {
			if (log.isErrorEnabled()) {
				log.error("Failed to locate Registry at host [" + host	+ "] on port [" + port + "]", e);
			}
		}
		
		if(log.isDebugEnabled())
		{
			log.debug("Registry found.");
		}

		return registry;
	}

	@Override
	public Remote findRemoteObjects(String host, int port, String remoteObject) throws RemoteObjectNotFoundException{

		Registry registry = this.getRegistry(host, port);

		if (registry != null) {
			try {
				return registry.lookup(remoteObject);
			} catch (AccessException e) {
				if (log.isErrorEnabled()) {
					log.error("RMI object ["+remoteObject+"] Access denied.",e );
				}
			} catch (RemoteException e) {
				if (log.isErrorEnabled()) {
					log.error("RMI object ["+remoteObject+"] RemoteException.", e);
				}
			} catch (NotBoundException e) {
				if (log.isErrorEnabled()) {
					log.error("RMI object ["+remoteObject+"] NotBoundException.",e );
				}
			}
		}
		
		
		throw new RemoteObjectNotFoundException("Remote Object ["+remoteObject+"]");
	}
	
	private Method findMethodWithName(Remote remote, String methodName, int argsLength) throws NoSuchMethodException
	{
		Class objectClass = remote.getClass();
		
		Method [] methods = objectClass.getMethods();
		

		for(Method method : methods)
		{
			if(method.getName().equalsIgnoreCase(methodName) && method.getParameterTypes().length == argsLength)
			{
				return method;
			}
		}
		
		throw new NoSuchMethodException("No such Method ["+methodName+"]" );
		
	}
	
	private Object invokeMethod(Object obj, Method method, Object ...args) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
	{
		Class [] parameterTypes = method.getParameterTypes();
		if((args != null && args.length != parameterTypes.length) || (parameterTypes.length == 0 && args != null))
		{
			throw new IllegalArgumentException("The input args length doesn't match the expected parameter length.");
		}
	
		
		List<Object> arguments = new ArrayList<Object>();
		if(args != null)
		{
			for(int i = 0; i < parameterTypes.length; i ++)
			{
				Object converted = simpleTypeConverter.convertIfNecessary(args[i], parameterTypes[i]);
				arguments.add(converted);
			}
		}
		
		return method.invoke(obj, arguments.toArray(new Object[arguments.size()]));
	}
	
	
	@Override
	public String [] listRemoteObjects(String host, int port) {
		// TODO Auto-generated method stub
		Registry registry = this.getRegistry(host, port);

		if (registry != null) {
			
			try {
				return registry.list();
			} catch (AccessException e) {
				if (log.isErrorEnabled()) {
					log.error("RMI Access denied, failed to list.",e );
				}
			} catch (RemoteException e) {
				if (log.isErrorEnabled()) {
					log.error("RMI RemoteException.", e);
				}
			} 
			

		}
		return null;
	}

	@Override
	public Object invokeRemoteMethod(String host, int port, String remoteObject, String methodName, Object... args)
	throws RemoteObjectNotFoundException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
		
		Remote remote = this.findRemoteObjects(host, port, remoteObject);
		
		Method method = this.findMethodWithName(remote, methodName, (args != null ? args.length : 0));
		
		return this.invokeMethod(remote, method, args);

	}

}

 

 

 

 

It’s very easy to write a utility tool to debug RMI using the above code by now. And here’s the screen snapshot of my tools.

 

 

Resources

 

1) Accelerate your RMI programming

2) RMI performance tips

3) Java remoting protocol benchmarks

4) Middleware remoting protocol migration

 

1
0
分享到:
评论
1 楼 ginge 2008-09-23  
The online editor is too terrible, it lose the formatting after saving as a draft article. And I've to re-do all the typing stuff...

Any one who wants to view the outcome of my tool please go to see my photo album.

相关推荐

    Rmi示例 Rmi代码示例

    RMI(Remote Method Invocation,远程方法调用)是Java平台中的一个重要特性,它允许Java对象在不同的Java虚拟机之间进行通信,实现分布式计算。RMI是Java开发分布式应用程序的基础,尤其在构建分布式服务和微服务...

    java_rmi.rar_RMI java_java.rmi

    Java RMI(Remote Method Invocation,远程方法调用)是Java平台提供的一种分布式计算技术,它允许Java对象在不同的网络环境中进行交互,就像它们在同一个进程内一样。RMI是Java在分布式系统领域的核心特性,极大地...

    java rmi java rmi

    根据提供的文件信息,我们可以深入探讨Java RMI(Java Remote Method Invocation)的相关知识点,包括其概念、原理、体系结构以及一个具体的示例。 ### RMI的概念 RMI是一种Java技术,它允许开发者创建分布式应用...

    RMI.rar_Java RMI_java.rmi_java.rmi.Remot_remote

    Java RMI(远程方法调用)是Java编程语言中的一项核心技术,自JDK 1.1版本起就被引入,用于构建分布式系统。RMI允许Java对象在不同的Java虚拟机(JVMs)之间进行交互,仿佛这些对象是在同一台机器上一样。这种技术的...

    java rmi 参考文档

    ### Java RMI (Remote Method Invocation) 概念与实践 #### 一、Java RMI简介 Java RMI(Remote Method Invocation)是一种允许调用不同Java虚拟机(JVM)上方法的机制。这些JVM可能位于不同的机器上,也可能在同一...

    java RMI实现代码

    Java RMI(Remote Method Invocation,远程方法调用)是Java平台提供的一种分布式计算技术,它允许在不同的Java虚拟机之间进行远程对象的调用。RMI使得开发者可以像调用本地对象一样调用网络上的对象,极大地简化了...

    JAVA RMI测试代码

    Java Remote Method Invocation (RMI) 是Java平台提供的一种分布式计算技术,它允许Java对象在不同的网络环境中进行交互,实现远程方法调用。本压缩包文件"rmi-code"包含了一个完整的RMI测试代码示例,适合在Linux和...

    JAVA RMI 传输 SSL加密

    Java RMI (Remote Method Invocation) 是一种用于在Java应用程序之间进行远程通信的技术。为了提高RMI通信的安全性,我们可以使用SSL (Secure Sockets Layer) 或其后继者TLS (Transport Layer Security) 进行加密。...

    SpringRMI小例子

    Spring Remote Method Invocation(RMI)是Java平台上的一个远程对象调用框架,它允许一个Java对象在一台机器上执行,并且被另一台机器上的客户端调用。在这个"SpringRMI小例子"中,我们将深入探讨如何利用Spring...

    spring中使用RMI

    在Spring框架中,远程方法调用(Remote Method Invocation, RMI)是一种使应用程序能够通过网络调用另一个JVM上的对象方法的技术。RMI是Java平台的一部分,它允许开发者创建分布式应用,使得对象可以像调用本地方法...

    分布式实验报告RMI.docx

    分布式实验报告 RMI.docx 本实验报告主要介绍了 Java RMI(Remote Method Invocation,远程方法调用)的基本概念和实现步骤。RMI 是一种分布式对象通讯机制,允许运行在一个 Java 虚拟机的对象调用运行在另一个 ...

    RMI原理及应用详解

    **RMI原理及应用详解** 远程方法调用(Remote Method Invocation,简称RMI)是Java平台提供的一种分布式计算技术,允许在不同的Java虚拟机(JVM)之间进行对象方法的透明调用。RMI的核心思想是使Java对象能够跨越...

    Ehcache RMI Replicated Cluster(RMI集群)

    Ehcache RMI Replicated Cluster 是一种分布式缓存解决方案,它使用远程方法调用(RMI)技术在多个节点之间复制数据,以实现高可用性和负载均衡。在大型分布式系统中,缓存是提高应用程序性能的关键组件,因为它可以...

    spring RMI简单例子

    Spring RMI(Remote Method Invocation)是Java平台上的远程方法调用技术,结合Spring框架的特性,使得在分布式系统中调用远程服务变得更加便捷。在这个简单的例子中,我们将深入理解Spring RMI的工作原理以及如何...

    基于JAVA RMI的聊天室

    **基于JAVA RMI的聊天室** Java Remote Method Invocation(RMI)是Java平台提供的一种用于在分布式环境中调用远程对象的方法。在这个“基于JAVA RMI的聊天室”项目中,开发者利用RMI技术构建了一个简单的多用户...

    java_rmi文档

    Java RMI(Remote Method Invocation,远程方法调用)是Java平台提供的一种分布式计算技术,它允许在不同的Java虚拟机之间进行方法调用,仿佛这些对象都在同一台机器上。RMI是Java网络编程的重要组成部分,使得开发...

    java RMI技术实现的网络聊天室

    Java RMI(Remote Method Invocation)技术是Java平台中用于分布式计算的一种机制,它允许一个Java对象调用远程计算机上的另一个Java对象的方法。在本案例中,“java RMI技术实现的网络聊天室”是一个使用RMI构建的...

    rmi_java项目实例

    本项目实例是基于RMI技术实现的一个服务器端程序,名为"RMIServer",提供了远程服务的接口和实现,下面将详细介绍RMI的基本概念、工作原理以及如何通过这个项目实例来学习和应用RMI。 1. **RMI基本概念**: - **...

    spring RMI 服务(自动把service发布为RMI服务)

    Spring RMI服务是一种在Java平台上实现远程方法调用(Remote Method Invocation, RMI)的技术,它允许分布式系统中的不同组件通过网络进行通信。在Spring框架的支持下,我们可以更方便地将服务发布为RMI服务,使得...

Global site tag (gtag.js) - Google Analytics