当前位置: 首页 > news >正文

.net 重复调用webservice_Java RMI 远程调用详解,优劣势说明

今天在看RPC看到了RMI这个东东,于是在网上查了学习了一下,借鉴了几个blog写的。

借鉴网站在最后有写。

Java RMI不是什么新技术,但却是是非常重要的底层技术。

概念

RMI(Remote Method Invocation,远程方法调用)是用Java在JDK1.2中实现的,它大大增强了Java开发分布式应用的能力。Java作为一种风靡一时的网络开发语言,其巨大的威力就体现在它强大的开发分布式网络应用的能力上,而RMI就是开发百分之百纯Java的网络分布式应用系统的核心解决方案之一。其实它可以被看作是RPC的Java版本。但是传统RPC并不能很好地应用于分布式对象系统。而Java RMI 则支持存储于不同地址空间的程序级对象之间彼此进行通信,实现远程对象之间的无缝远程调用。

RMI 调用步骤

6a80fa72493f0497de0e1a18ad46c64b.png

RMI远程调用步骤:

1,客户对象调用客户端辅助对象上的方法

2,客户端辅助对象打包调用信息(变量,方法名),通过网络发送给服务端辅助对象

3,服务端辅助对象将客户端辅助对象发送来的信息解包,找出真正被调用的方法以及该方法所在对象

4,调用真正服务对象上的真正方法,并将结果返回给服务端辅助对象

5,服务端辅助对象将结果打包,发送给客户端辅助对象

6,客户端辅助对象将返回值解包,返回给客户对象

7,客户对象获得返回值

搭建一个RMI服务

创建HelloInterface

package rmi;import java.io.Serializable;import java.rmi.Remote;import java.rmi.RemoteException;public interface HelloInterface extends Remote, Serializable {    /**     * 远程接口方法必须抛出 java.rmi.RemoteException     * 否则会报错,大家可以去掉看一下错误内容     */    String sayHello() throws RemoteException;}

创建HelloImpl

package rmi;import java.rmi.RemoteException;import java.rmi.server.UnicastRemoteObject;public class HelloImpl extends UnicastRemoteObject implements HelloInterface {    private String message;    /**     * 必须定义构造方法,即使是默认构造方法,     * 也必须把它明确地写出来,因为它必须抛出出RemoteException异常     * @param msg     * @throws RemoteException     */    public HelloImpl(String msg) throws RemoteException {        this.message = msg;    }    /**     * @return     * @throws RemoteException     * @Description:     * @author xingle     * @data 2015-9-28 下午4:39:41     */    @Override    public String sayHello() throws RemoteException {        System.out.println("Called by HelloClient");        return message;    }}

创建HelloServer:

package rmi;import java.net.MalformedURLException;import java.rmi.Naming;import java.rmi.RemoteException;import java.rmi.registry.LocateRegistry;/** *  服务端 * @author pine * @date 20200116 */public class HelloServer {    public static void main(String[] args) {        try {            // 启动RMI注册服务,指定端口为1099 (1099为默认端口)            LocateRegistry.createRegistry(1099);            // 创建远程对象的一个或多个实例            // 可以用不同名字注册不同的实例            HelloImpl service = new HelloImpl("hello,world!");            // 如果要把hello实例注册到另一台启动了RMI注册服务的机器上            // Naming.rebind("//192.168.1.105:1099/Hello",hello);            Naming.rebind("Hello", service);            System.out.println("Hello Server is ready.");        } catch (RemoteException e) {            System.out.println("Hello Server failed: " + e);            e.printStackTrace();        } catch (MalformedURLException e) {            e.printStackTrace();        }    }}

创建HelloClient:

package rmi;import java.rmi.Naming;/** * 客户端 * @author pine * @date 20200116 */public class HelloClient {    public static void main(String[] argv) {        try {            // 如果要从另一台启动了RMI注册服务的机器上查找hello实例            HelloInterface hello = (HelloInterface)Naming.            lookup("//127.0.0.1:1099/Hello");            // 调用远程方法            System.out.println(hello.sayHello());        } catch (Exception e) {            System.out.println("HelloClient exception: " + e);        }    }}

一个RMI服务就这样完成了,然后运行服务端HelloServer.java ,再运行客户端

HelloClient.java,然后观察控制台打印内容:

bdb0cbbea0f83dd0ed69bf08917aa164.png

客户端

6a34af5f570610891fc247b5a9aacf87.png

服务端

RMI的优点

这种机制给分布计算的系统设计、编程都带来了极大的方便。只要按照RMI规则设计程序,可以不必再过问在RMI之下的网络细节了,如:TCP和Socket等等。任意两台计算机之间的通讯完全由RMI负责。调用远程计算机上的对象就像本地对象一样方便。

1、面向对象:

RMI可将完整的对象作为参数和返回值进行传递,而不仅仅是预定义的数据类型。也就是说,可以将类似Java Hash表这样的复杂类型作为一个参数进行传递。

2、可移动属性:

RMI可将属性从客户机移动到服务器,或者从服务器移动到客户机。

3、设计方式:

对象传递功能使你可以在分布式计算中充分利用面向对象技术的强大功能,如二层和三层结构系统。如果用户能够传递属性,那么就可以在自己的解决方案中使用面向对象的设计方式。所有面向对象的设计方式无不依靠不同的属性来发挥功能,如果不能传递完整的对象——包括实现和类型——就会失去设计方式上所提供的优点。

4、安全性:

RMI使用Java内置的安全机制保证下载执行程序时用户系统的安全。RMI使用专门为保护系统免遭恶意小程序侵害而设计的安全管理程序。

5、便于编写和使用

RMI使得Java远程服务程序和访问这些服务程序的Java客户程序的编写工作变得轻松、简单。远程接口实际上就是Java接口。为了实现RMI的功能必须创建远程对象任何可以被远程调用的对象必须实现远程接口。但远程接口本身并不包含任何方法。因而需要创建一个新的接口来扩展远程接口。新接口将包含所有可以远程调用的方法。远程对象必须实现这个新接口,由于新的接口扩展了远程接口,实现了新接口,就满足了远程对象对实现远程接口的要求,所实现的每个对象都将作为远程对象引用。

RMI的劣势

从上面的过程来看,RMI对服务器的IP地址和端口依赖很紧密,但是在开发的时候不知道将来的服务器IP和端口如何,但是客户端程序依赖这个IP和端口。这也是RMI的局限性之一。这个问题有两种解决途径:一是通过DNS来解决,二是通过封装将IP暴露到程序代码之外。RMI的局限性之二是RMI是Java语言的远程调用,两端的程序语言必须是Java实现,对于不同语言间的通讯可以考虑用Web Service或者公用对象请求代理体系(CORBA)来实现。

RMI与Socket的比较

RMI技术比较socket的网络编程主要有以下几个方面:

第一、RMI是面向对象的,而后者不是。

第二、RMI是与语言相绑定的。比如当你使用Java RMI技术的时候,客户端与服务器端都必须使用Java开发。而socket的网络编程是使用独立于开发语言的,甚至独立于平台。基于socket的网络编程,客户端与服务器端可以使用不同开发语言和不同的平台。

第三、从网络协议栈的观点来看,RMI与socket的网络编程处于不同层次上。基于socket的网络编程位于TCP协议之上,而RMI在TCP协议之上,又定义了自己的应用协议,其传输层采用的是Java远程方法协议(JRMP)。可见,在网络协议栈上,基于RMI的应用位置更高一些,这也决定了,与socket的网络编程相比,RMI会丧失一些灵活性和可控性,但是好处是它带给了应用开发者更多的简洁,方便和易用。比如:如果你用的是RMI,你不需要关心消息是怎么序列化的,你只需要像本地方法调用一样,使用RMI。代价是:应用开发者无法很好地控制消息的序列化机制。

第四、性能这是最后一点不同,我认为也是比较重要的一点,就是两种方法的性能比较,其往往决定着你将使用那种技术来开发你的应用。实验的结果是:RMI与TCP based socket相比,传输相同的有效数据,RMI需要占用更多的网络带宽(protocol overhead)。从这里,我们可以得出一个一般性的结论:RMI主要是用于远程方法的”调用“(RMI是多么的名符其实:)),其技术内涵强调的是 “调用”,基于此,我能想到的是:移动计算,和远程控制,当你的应用不需要在client与server之间传输大量的数据时,RMI是较好的选择,它简洁、易于开发。但是,一旦你的应用需要在client与server之间传输大量的数据,极端的,比如FTP应用,则RMI是不适合的,我们应该使用 socket。

PS: RMI的效率还是很高的,一般情况下会比Hessian更高效,比Web Service更是高效很多;当然和socket这种东东相比,当然要低效一点了,socket更底层一些啊。RMI的具体实现,依然是依赖于底层的Socket编程。

本文参考内容:

参考资料:http://java.sun.com/developer/onlineTraining/Programming/JDCBook/rmi.htmlhttp://en.wikipedia.org/wiki/Java_remote_method_invocationhttp://csevan.javaeye.com/blog/284613http://dev.firnow.com/course/3_program/java/javajs/2009110/154540.html

http://developer.51cto.com/art/200906/130417.htm (这篇非常不错:用RMI实现基于Java的分布式计算)

https://www.cnblogs.com/ninahan0419/archive/2009/06/25/JavaRMI.html

希望阅读我,每个人都有收获,如果感觉不错可以转发一下大家一起学习。

相关文章:

  • 惠普刀片服务器c7000硬件配置手册_刀片服务器的优劣势概述
  • android 增删改查 源码_flask mysql 数据库增删改查(微信报修小程序源码讲解四)...
  • $emit传递多个参数_PPC和MIPS指令集下二进制代码中函数参数个数的识别方法
  • 如何把项目改成微服务项目_微服务项目搭建,到底要不要聚合工程?
  • cmd python封装成exe_将python代码打包成exe文件——pyinstaller模块用法
  • js不用reverse反转数组代码_反转数组而不使用Array.Reverse()
  • jsch设置代理_Springboot2(20)轻松搞定WebSocket
  • adb 输入回车命令_adb 常用命令
  • matlab向量与x正方向的夹角_高中数学:向量在几何中的应用
  • 怎么判断几行_孩子没有天赋怎么办?小陶虹的回答我点100个赞
  • 执行时间单位_排污许可申报之后环境管理台账及执行报告,你准备好了吗?
  • 人体一机竞技格斗机器人_2019中国智能机器人大赛在青岛举行
  • cad lisp 界址点号_CAD图纸多到打不完?没关系学会批量打印来多少都不怕
  • mysql 动态传入表名 存储过程_MySQL存储过程了解
  • zbbz 坐标标注lisp_CAD中还能这样快速标注尺寸?怪不得同事天天准时下班
  • [PHP内核探索]PHP中的哈希表
  • 【跃迁之路】【519天】程序员高效学习方法论探索系列(实验阶段276-2018.07.09)...
  • Android 控件背景颜色处理
  • Angular 响应式表单 基础例子
  • const let
  • ECS应用管理最佳实践
  • fetch 从初识到应用
  • Github访问慢解决办法
  • Git学习与使用心得(1)—— 初始化
  • java8 Stream Pipelines 浅析
  • javascript 总结(常用工具类的封装)
  • JavaScript中的对象个人分享
  • Java多态
  • leetcode98. Validate Binary Search Tree
  • mongo索引构建
  • Promise初体验
  • 和 || 运算
  • 极限编程 (Extreme Programming) - 发布计划 (Release Planning)
  • 想晋级高级工程师只知道表面是不够的!Git内部原理介绍
  • 小而合理的前端理论:rscss和rsjs
  • 新版博客前端前瞻
  • JavaScript 新语法详解:Class 的私有属性与私有方法 ...
  • ​Distil-Whisper:比Whisper快6倍,体积小50%的语音识别模型
  • ​MySQL主从复制一致性检测
  • #在 README.md 中生成项目目录结构
  • (delphi11最新学习资料) Object Pascal 学习笔记---第7章第3节(封装和窗体)
  • (JS基础)String 类型
  • (附源码)计算机毕业设计SSM基于健身房管理系统
  • (强烈推荐)移动端音视频从零到上手(下)
  • (一)u-boot-nand.bin的下载
  • (转)Groupon前传:从10个月的失败作品修改,1个月找到成功
  • (转)mysql使用Navicat 导出和导入数据库
  • (转)ORM
  • ***微信公众号支付+微信H5支付+微信扫码支付+小程序支付+APP微信支付解决方案总结...
  • .net core webapi Startup 注入ConfigurePrimaryHttpMessageHandler
  • .NET 材料检测系统崩溃分析
  • /usr/bin/python: can't decompress data; zlib not available 的异常处理
  • :“Failed to access IIS metabase”解决方法
  • :如何用SQL脚本保存存储过程返回的结果集
  • [ vulhub漏洞复现篇 ] JBOSS AS 5.x/6.x反序列化远程代码执行漏洞CVE-2017-12149