RMI(远程方法调用)学习笔记

RMI是Java的一组拥护开发分布式应用程序API。RMI使用Java语言接口定义了远程对象,它集合了Java序列化和Java远程方法协议(Java Remote Method Protocol)。简单地说,这样使原先的程序在同一操作系统的方法调用,变成了不同操作系统之间程序的方法调用,由于J2EE是分布式程序平台,它以RMI机制实现程序组件在不同操作系统之间的通信。比如,一个EJB可以通过RMI调用Web上另一台机器上的EJB远程方法。(来自百度百科)  公司的游戏项目服务端采用Java架构的,在实现游戏跨服通信采用的技术就是RMI技术。RMI在传输速度上虽然没有纯Socket方式快,但是接口简洁,学习门槛比较低,开发速度快。


RMI开发步骤:

1. 创建RMI接口对象,这是实现双方通信的规范,需要继承Remote接口

2. 创建一个具体的类来实现上边的通信接口,注意此类必须继承UnicastRemoteObject

3. 在服务端注册一个RMI服务,监听请求

4. 客户端通过JNDI( Java Naming and Directory Interface )找到目标服务,并调用远程方法

下边演示一个简单的例子。 (服务端与客户端只是主方法代码不同

首先为服务建立一个实体类,注意因为此对象需要现实进行远程传输,所以必须继承Serializable接口

public class Person  implements Serializable{

	private static final long serialVersionUID = 1L;
	private String name;
	private int age;
	

	public String getName() {
		return name;
	}

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

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
	 
	public String toString(){
		return "姓名:"+name+","+"年龄:"+age;
	}
	 
}


创建RMI接口PersonService,注意远程接口需要继承Remote,而且每一个接口方法都必须抛出RemoteException异常

public interface IPersonService extends Remote{

	public List<Person> getPersonList(long sendTime) throws RemoteException;
    }

编写 PersonService的实现类,必须继承UnicastRemoteObject类

public class PersonService extends UnicastRemoteObject  implements IPersonService{

	public PersonService() throws RemoteException{
		
	}
	@Override
	public List<Person> getPersonList(long recevieTime) throws RemoteException {
		List<Person> pList = new ArrayList<Person>();
		
		Person p1 =new Person();
		p1.setName("Lily");
		p1.setAge(15);
		
		Person p2 =new Person();
		p2.setName("Lucy");
		p2.setAge(16);
		
		pList.add(p1);
		pList.add(p2);
		
		long now = System.currentTimeMillis();
		System.err.println("服务端收到数据并处理,耗时毫秒数"+(now-recevieTime));
		
		return pList;
	}
    }
服务端测试代码

public class Test {
	public static void main(String[] args)  throws Exception{
		
		IPersonService service = new PersonService();
		
		LocateRegistry.createRegistry(8890);
		
		Naming.bind("rmi://127.0.0.1:8890/PersonService", service);
	
		System.err.println("服务端开始监听请求。。。");
	}
	
    }
客户端测试代码

public class Test {
	public static void main(String[] args)  throws Exception{
		String rmiPath = "rmi://127.0.0.1:8890/PersonService";
		System.err.println("客户端开始请求数据。。。");
		long begin = System.currentTimeMillis();
		IPersonService service = (IPersonService)Naming.lookup(rmiPath);
		
		//调用rmi接口所有方法都是阻塞的……
		 List<Person> list  = service.getPersonList(begin);
		
		 for(Person p:list){
			 System.err.println(p);
		 }
		 try{
			 //模拟处理其他逻辑
			 Thread.sleep(200);
		 }catch(Exception e){
			 
		 }
		 long now = System.currentTimeMillis();
		 System.err.println("客户端接受数据并处理,耗时毫秒数:"+(now-begin));
	}
    }


运行结果:



从运行结果可以看出,此通信方式为阻塞模式,客户端必须等服务端响应后才可以执行其他逻辑。

当客户端的请求次数达到一定规模的话,服务端会很容易遇到瓶颈。


改进方式:

1. 服务端采用线程池机制,并发处理请求

2. 修改通信方式为异步请求,客户端发出请求后继续执行其他逻辑而不等待,服务端定时处理来自客户端的请求队列并响应结果。通过回调的方式处理客户端的后续操作

 
 

你可能感兴趣的:(java,rmi)