热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

关于rmi——各种资料的摘抄

 背景Distributedsystemsrequirethatcomputationsrunningindifferentaddressspaces,potentiallyond

 

背景

Distributed systems require that computations running in different address spaces, potentially on different hosts, be able to communicate. For a basic communication mechanism, the JavaTM programming language supports sockets, which are flexible and sufficient for general communication. However, sockets require the client and server to engage in applications-level protocols to encode and decode messages for exchange, and the design of such protocols is cumbersome and can be error-prone.

An alternative to sockets is Remote Procedure Call (RPC), which abstracts the communication interface to the level of a procedure call. Instead of working directly with sockets, the programmer has the illusion of calling a local procedure, when in fact the arguments of the call are packaged up and shipped off to the remote target of the call. RPC systems encode arguments and return values using an external data representation, such as XDR.

RPC, however, does not translate well into distributed object systems, where communication between program-level objects residing in different address spaces is needed. In order to match the semantics of object invocation, distributed object systems require remote method invocation or RMI. In such systems, a local surrogate (stub) object manages the invocation on a remote object.

 谷歌翻译:分布式系统要求在不同地址空间(可能在不同主机上)运行的计算能够进行通信。对于基本通信机制,JavaTM编程语言支持套接字,这些套接字灵活且足以进行一般通信。然而,套接字要求客户端和服务器参与应用程序级协议以对消息进行编码和解码以进行交换,并且这种协议的设计是麻烦的并且可能容易出错。

套接字的替代方法是远程过程调用(RPC),它将通信接口抽象到过程调用的级别。程序员不是直接使用套接字,而是具有调用本地过程的错觉,实际上调用的参数被打包并运送到远程调用目标。 RPC系统使用外部数据表示(例如XDR)对参数和返回值进行编码。

但是,RPC不能很好地转换为分布式对象系统,其中需要驻留在不同地址空间中的程序级对象之间的通信。为了匹配对象调用的语义,分布式对象系统需要远程方法调用或RMI。在此类系统中,本地代理(存根)对象管理远程对象上的调用。

 

Java RMI,即 远程方法调使用(Remote Method Invocation),

It is a mechanism that allows an object residing in one system (JVM) to access/invoke an object running on another JVM.

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

一种使用于实现远程过程调使用(RPC)(Remote procedure call)的Java API, 可以直接传输序列化后的Java对象和分布式垃圾收集。它的实现依赖于Java虚拟机(JVM),因而它仅支持从一个JVM到另一个JVM的调使用。

 

in an RMI application, we write two programs, a server program (resides on the server) and a client program (resides on the client).



  • Inside the server program, a remote object is created and reference of that object is made available for the client (using the registry).



  • The client program requests the remote objects on the server and tries to invoke its methods.



框架:



  • Transport Layer − This layer connects the client and the server. It manages the existing connection and also sets up new connections.



  • Stub − A stub is a representation (proxy) of the remote object at client. It resides in the client system; it acts as a gateway for the client program.



  • Skeleton − This is the object which resides on the server side. stub communicates with this skeleton to pass request to the remote object.



  • RRL(Remote Reference Layer) − It is the layer which manages the references made by the client to the remote object.




  • Working of an RMI Application

    The following points summarize how an RMI application works −



    • When the client makes a call to the remote object, it is received by the stub which eventually passes this request to the RRL.



    • When the client-side RRL receives the request, it invokes a method called invoke() of the object remoteRef. It passes the request to the RRL on the server side.



    • The RRL on the server side passes the request to the Skeleton (proxy on the server) which finally invokes the required object on the server.



    • The result is passed all the way back to the client.





举例

 

 


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 prices;
protected WarehouseImpl() throws RemoteException
{
prices = new HashMap();
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
17 WarehouseImpl centralWarehouse = new WarehouseImpl();
18
19 //创建注册表
20 LocateRegistry.createRegistry(1099);
//bind方法绑定了RMI地址与RMI服务实现类。发布服务
21 Naming.bind("rmi://localhost:1099/central_warehoues",centralWarehouse);
22
23
24 }
25 }

 


 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
14 String url = "rmi://localhost:1099/central_warehoues";
15 Warehouse centralWarehouse = (Warehouse) Naming.lookup(url);//centralWarehouse相当于stub
16 String descr = "mate7";
17 double price = centralWarehouse.getPrice(descr);
18 System.out.println(descr + ":" + price);
19 }
20 }



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


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



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



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

 

 

 


RMI的局限性

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

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

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

资料来源:
Java Remote Method Invocation Specification
分布式架构基础:Java RMI详解-新闻热点
对JAVA RMI的认识 - 冬瓜蔡 - 博客园
https://www.tutorialspoint.com/java_rmi/java_rmi_introduction.htm

 

 


推荐阅读
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
  • 本文讨论了在openwrt-17.01版本中,mt7628设备上初始化启动时eth0的mac地址总是随机生成的问题。每次随机生成的eth0的mac地址都会写到/sys/class/net/eth0/address目录下,而openwrt-17.01原版的SDK会根据随机生成的eth0的mac地址再生成eth0.1、eth0.2等,生成后的mac地址会保存在/etc/config/network下。 ... [详细]
  • (三)多表代码生成的实现方法
    本文介绍了一种实现多表代码生成的方法,使用了java代码和org.jeecg框架中的相关类和接口。通过设置主表配置,可以生成父子表的数据模型。 ... [详细]
  • 本文讨论了在VMWARE5.1的虚拟服务器Windows Server 2008R2上安装oracle 10g客户端时出现的问题,并提供了解决方法。错误日志显示了异常访问违例,通过分析日志中的问题帧,找到了解决问题的线索。文章详细介绍了解决方法,帮助读者顺利安装oracle 10g客户端。 ... [详细]
  • 使用eclipse创建一个Java项目的步骤
    本文介绍了使用eclipse创建一个Java项目的步骤,包括启动eclipse、选择New Project命令、在对话框中输入项目名称等。同时还介绍了Java Settings对话框中的一些选项,以及如何修改Java程序的输出目录。 ... [详细]
  • 本文概述了JNI的原理以及常用方法。JNI提供了一种Java字节码调用C/C++的解决方案,但引用类型不能直接在Native层使用,需要进行类型转化。多维数组(包括二维数组)都是引用类型,需要使用jobjectArray类型来存取其值。此外,由于Java支持函数重载,根据函数名无法找到对应的JNI函数,因此介绍了JNI函数签名信息的解决方案。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • JVM 学习总结(三)——对象存活判定算法的两种实现
    本文介绍了垃圾收集器在回收堆内存前确定对象存活的两种算法:引用计数算法和可达性分析算法。引用计数算法通过计数器判定对象是否存活,虽然简单高效,但无法解决循环引用的问题;可达性分析算法通过判断对象是否可达来确定存活对象,是主流的Java虚拟机内存管理算法。 ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
author-avatar
allenn2012
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有