对javarmi的认识

冬瓜蔡      2022-06-10     751

关键词:

RMI的定义

RPC (Remote Procedure Call):远程方法调用,用于一个进程调用另一个进程中的过程,从而提供了过程的分布能力。

RMI(Remote Method Invocation):远程方法调用,即在RPC的基础上有向前迈进了一步,提供分布式对象间的通讯。允许运行在一个java 虚拟机的对象调用运行在另一个java虚拟机上对象的方法。这两个虚拟机可以是运行在相同计算机上的不同进程中,也可以是运行在网络上的不同计算机中。

RMI的全称宗旨就是尽量简化远程接口对象的调用。

RMI大大增强了java开发分布式应用的能力,例如可以将计算方法复杂的程序放在其他的服务器上,主服务器只需要去调用,而真正的运算是在其他服务器上进行,最后将运算结果返回给主服务器,这样就减轻了主服务器的负担,提高了效率(但是也有其他的开销)。

RMI网络模型

在设计初始阶段,我们真正想要的是这样一种机制,客户端程序员以常规方式进行方法调用,而无需操心将数据发送到网络上或者解析响应之类的问题。所以才有了如下的网络模型:在客户端为远程对象安装一个代理。代理是位于客户端虚拟机中的一个对象,它对于客户端程序来说,就像是要访问的远程对象一样。客户端调用此代理时,只需进行常规的方法调用。而客户端代理则负责使用网络协议与服务器进行联系。

 

现在的问题在于代理之间是如何进行通信的?通常有三种方法:

1、CORBA:通过对象请求代理架构,支持任何编程语言编写的对象之间的方法调用。

2、SOAP

3、RMI:JAVA的远程方法调用技术,支持java的分布式对象之间的方法调用。

其中CORBA与SOAP都是完全独立于言语的,可以使用C、C++、JAVA来编写,而RMI只适用于JAVA。

RMI的工作原理

一、术语介绍

1、存根:当客户端要调用远程对象的一个方法时,实际上调用的是代理对象上的一个普通方法,我们称此代理对象为存根(stub)。存根位于客户端机器上,而非服务器上。

2、参数编组:存根会将远程方法所需的参数打包成一组字节,对参数编码的过程就称为参数编组。参数编组的目的是将参数转换成适合在虚拟机之间进行传递的格式,在RMI协议中,对象是使用序列化机制进行编码的。

二、编程模型

为了介绍RMI的编程模型,我下面会编写一个DEMO。远程对象表示的是一个仓库,而客户端程序向仓库询问某个产品的价格。

1、接口定义

远程对象的能力是由在客户端和服务器之间共享的接口所表示的:

 

package rmi;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface Warehouse extends Remote
{
    double getPrice(String description) throws RemoteException;
}

 

远程对象的接口必须扩展Remote接口,它位于java.rmi包中。接口中所有的方法必须声明抛出RemoteException异常。这是因为远程方法总是存在失败的可能,所以java编程语言要求每一次远程方法的调用都必须捕获RemoteException,并且指明当调用不成功时应执行的相应处理操作。

2、接口的实现

package rmi;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.HashMap;
import java.util.Map;

public class WarehouseImpl extends UnicastRemoteObject implements Warehouse
{
    private static final long serialVersionUID = 1L;
    private Map<String,Double> prices;
    protected WarehouseImpl() throws RemoteException
    {
        prices = new HashMap<String,Double>();
        prices.put("mate7",3700.00);
        
    }
    public double getPrice(String description) throws RemoteException
    {
        Double price = prices.get(description);
        return price == null? 0 : price;
    }

}

你可以看出这个类是远程方法调用的目标,因为它扩展自UnicastRemoteObject,这个类的构造器使得它的对象可供远程访问。

3、RMI注册表:通过JNDI发布RMI服务

1、要访问服务器上的一个远程对象时,客户端必须先得到一个本地的存根对象,也就是客户端机器上的代理对象。那么问题来了,如何才能得到这个存根呢?

2、为此,JDK提供了自举注册服务(bootstrap registry service),服务器程序应该使用自举注册服务来注册至少一个远程对象。

3、而要注册一个远程对象,需要一个RMI URL和一个对实现对象的引用。

4、RMI 的URL以rmi:开头,后接域名或IP地址(host),紧接着是端口号(port),最后是服务名(service)。

     如:rmi://regserver.mycompany.cmo:99/central_warehouse

     如果我们是在本地发布RMI服务,那么host就是“localhost”,此外RMI默认的端口号是“1099”,当然我们也可以自行设置,只要不与其他端口重复即可。              service实际上是基于同一个host与port下唯一的服务名。

发布RMI服务:

 1 package rmi;
 2 
 3 import java.net.MalformedURLException;
 4 import java.rmi.AlreadyBoundException;
 5 import java.rmi.Naming;
 6 import java.rmi.RemoteException;
 7 import java.rmi.registry.LocateRegistry;
 8 
 9 import javax.naming.NamingException;
10 
11 
12 public class WarehouseServer
13 {
14     public static void main(String[] args) throws RemoteException, NamingException, MalformedURLException, AlreadyBoundException
15     {
16         System.out.println("Constructing server implementation");
17         WarehouseImpl centralWarehouse = new WarehouseImpl();
18         
19         System.out.println("Binding server implementation to registry");
20         LocateRegistry.createRegistry(1099);
21         Naming.bind("rmi://localhost:1099/central_warehoues",centralWarehouse);
22         
23         System.out.println("Waiting for invocations from clients ...");
24     }
25 }

运行结果:

Constructing server implementation
Binding server implementation to registry
Waiting for invocations from clients ...

1、第20行只需提供一个port,就在JNDI中创建了一个注册表。

2、第21行通过bind方法绑定了RMI地址与RMI服务实现类。

3、执行这个方法后,相当于自动发布了RMI服务。接下来要做的事情就是写一个RM客户端调用已发布的RMI服务。

 4、调用RMI服务

 1 package rmi;
 2 
 3 import java.net.MalformedURLException;
 4 import java.rmi.Naming;
 5 import java.rmi.NotBoundException;
 6 import java.rmi.RemoteException;
 7 import javax.naming.NamingException;
 8 
 9 public class WarehouseClient
10 {
11     public static void main(String[] args) throws NamingException, RemoteException, MalformedURLException, NotBoundException
12     {
13         System.out.println("RMI registry binding:");
14         String url = "rmi://localhost:1099/central_warehoues";
15         Warehouse centralWarehouse = (Warehouse) Naming.lookup(url);
16         String descr = "mate7";
17         double price = centralWarehouse.getPrice(descr);
18         System.out.println(descr + ":" + price);
19     }
20 }

运行结果:

RMI registry binding:
mate7:3700.0

1、服务调用只需要知道两个东西:1、RMI请求路径;2、RMI接口名

2、第15行,这里用的是接口名Warehouse,而不是实现类。一定不能RMI接口的实现类,否则就是本地调用了。

3、查看运行结果,我们知道这次DEMO展示的远程调用成功了。

5、下面我们来看下RMI的网络示意图:

 

1、借助JNDI这个所谓的命名与目录服务,我们成功地发布并调用了RMI服务。实际上,JNDI就是一个注册表,服务端将服务对象放入到注册表中,客户端从注册表中获取服务对象。

2、在服务端我们发布了RMI服务,并在JNDI中进行了注册,此时就在服务端创建了一个Skeleton(骨架),当客户端第一次成功连接JNDI并获取远程服务对象后,立马在本地创建了一个Stub(存根)。

3、远程通信实际是通过Skeleton与Stub来完成的,数据是基于TCP/IP协议,在“传输层”上发送的。

4、毋庸置疑,理论上RMI一定比WebService要快,毕竟WebService是基于http协议的,而http所携带的数据是通过“应用层”来传输的。传输层较应用层更为底层,越底层越快。

RMI的局限性

1、只能实现JAVA系统之间的调用,而WebService可以实现跨语言实现系统之间的调用。

2、RMI使用了JAVA默认的序列化方式,对于性能要求比较高的系统,可能需要其他的序列化方案来解决。

3、RMI服务在运行时难免会存在故障,例如,如果RMI服务无法连接了,就会导致客户端无法响应的现象。

javarmi利用入门学习

Windows中遇到了JavaRMI,反弹又不那么方便,这时该如何利用呢?It’saquestion。正好加强Java学习了。0X00预备知识理解JavaRMI——Java远程调用提供了不同机器之间进行对象方法访问的能力,这样的构架允许一台机器的对象访... 查看详情

javarmi的一个简单实例

参考网站 http://www.cnblogs.com/leslies2/archive/2011/05/20/2051844.html实体类PersonEntitypackagenet.cs30.rmi;importjava.io.Serializable;/***Createdbycaochenghuaon2017/4/4.*/publicclassPersonEntityimple 查看详情

对“认识”的认识

很早就想谈谈关于“认识”的认识。这是一个宏大深刻的哲学问题。只是觉得没有完全思考清楚,还以为观点有些偏颇,担心自己没能力系统论述,就迟迟没有动笔。但想到谈论的问题本身就是一个偏颇的问题,而且,我始终觉... 查看详情

javarmi

RMI 相关知识RMI全称是Remote Method Invocation-远程方法调用,Java RMI在JDK1.1中实现的,其威力就体现在它强大的开发分布式网络应用的能力上,是纯Java的网络分布式应用系统的核心解决方案之一。其实它可以被看作是... 查看详情

javarmi远程通讯

  分布式计算系统要求运行在不同地址空间不同主机上的对象互相调用,在Java里提供了完整的sockets通讯接口,但sockets要求客户端和服务端必须进行应用级协议的编码交换数据,采用sockets是非常麻烦的。  一个代替Sockets的协... 查看详情

javarmi地址解析问题(代码片段)

我正在尝试重新编写一些基本的设计模式。我只有代码片段,没有完整的运行代码示例。一种叫做代理模式。我只想通过远程调用方法。这是我的简单代码:WebService.JavapublicclassWebServiceextendsUnicastRemoteObjectimplementsIRemoteprivatestaticf... 查看详情

javarmi分布式原理和应用

  RMI(RemoteMethodInvocation)是JAVA早期版本(JDK1.1)提供的分布式应用解决方案,它作为重要的API被广泛的应用在EJB中。随着互联网应用的发展,分布式处理任务也随之复杂起来,WebService也得到普遍的推广和应用。   &n... 查看详情

javarmi(代码片段)

查看详情

对编译原理的认识

认识:编译原理是把我们编写的高级语言通过一定的算法转换生成机器执行的二进制代码。好处:学习编译原理可以让我们对语法和数据结构有一个更深层次的认识,可以让我们理解机器是如何理解高级语言的,我们可以学习其... 查看详情

面试题思考:javarmi与rpc,jms的比较

RPC:(RemoteProcedureCall)   被设计为在应用程序间通信的平台中立的方式,它不理会操作系统之间以及语言之间的差异。支持多语言RMI:(RemoteMethodInvocation) RPC的Java版本,EJB的基础技术 RMI采用JRMP(JavaRemoteMethodProt... 查看详情

对hashcode的认识

对HashCode的认识:(“HashCode”是“哈希码”的同义词。)什么是哈希码(HashCode)在Java中,哈希码代表对象的特征。(哈希码就是对象的身份证)例如对象 String str1 = “aa”, str1.hashCode= 3104String str2 = “bb... 查看详情

对volatile的认识

volatile和synchronize的区别1.volatile不能保证原子性,只能修饰参数可见性,synchronize可以保证线程安全2.volatile只能修饰参数,不能修饰方法,synchronize只能修饰方法3.当对同一个参数进行多个线程时,可以使用volatile修饰,因为参数... 查看详情

浅谈javarmi

浅谈JAVA-RMIserverdemo:packagecom.ray.rmi;importjava.rmi.Naming;importjava.rmi.Remote;importjava.rmi.RemoteException;importjava.rmi.registry. 查看详情

对各组项目的认识

...来的项目讲解和进度汇报,我对各组的项目有一些片面的认识和疑问,以下仅代表我个人的观点,可能存在不正确和不合理的地方,望相应的作者能够谅解,同时我所做的系统也存在很多的问题和漏洞,希望各位能够批评指正,... 查看详情

请谈谈对soa的认识。

请谈谈对SOA的认识。 解答:面向服务的体系结构(Service-OrientedArchitecture,SOA)是一个组件模型,它将应用程序的不同功能单元(称为服务)通过这些服务之间定义良好的接口和契约联系起来。接口是采用中立的方式进行定... 查看详情

对imap邮箱协议的重新认识

对IMAP邮箱协议的重新认识重新认识IMAP邮箱协议参考资料是否有使用outlook配置POP误收服务器的邮件,导致所有的邮件仅在本地可查看?或者使用outlook邮件归档后,服务器的邮件全部下载到本地后悔?重新认识IMAP... 查看详情

javarmi学习笔记(代码片段)

前言开始学习一下Java中RMI的相关知识。RMI是我目前为止学起来比较难的一块,主要的原因就是一我没学过计网,对于这种通信相对来说有点陌生,很多文章后面的抓包分析我也看不懂。二就是初学Java,很多东西... 查看详情

javarmi学习笔记(代码片段)

前言开始学习一下Java中RMI的相关知识。RMI是我目前为止学起来比较难的一块,主要的原因就是一我没学过计网,对于这种通信相对来说有点陌生,很多文章后面的抓包分析我也看不懂。二就是初学Java,很多东西... 查看详情