这里是修真院后端小课堂,每篇分享文从
【背景介绍】【知识剖析】【常见问题】【解决方案】【编码实战】【扩展思考】【更多讨论】【参考文献】
八个方面深度解析后端知识/技能,本篇分享的是:
【RMI的简单介绍。】
大家好,我是IT修真院郑州分院第11期的学员何爽,一枚正直纯洁善良的后端程序员,今天给大家分享一下,修真院官网java(职业)任务8,深度思考中的知识点——RMI的简单介绍。
1.背景介绍
什么是RMI:
RMI全称是Remote Method Invocation-远程方法调用,Java RMI在JDK1.1中实现的,其威力就体现在它强大的开发分布式网络应用的能力上,是纯Java的网络分布式应用系统的核心解决方案之一。其实它可以被看作是RPC的Java版本。但是传统RPC并不能很好地应用于分布式对象系统。而Java RMI 则支持存储于不同地址空间的程序级对象之间彼此进行通信,实现远程对象之间的无缝远程调用。
RMI目前使用Java远程消息交换协议JRMP(Java Remote Messaging Protocol)进行通信。由于JRMP是专为Java对象制定的,Java RMI具有Java的"Write Once,Run Anywhere"的优点,是分布式应用系统的百分之百纯Java解决方案。用Java RMI开发的应用系统可以部署在任何支持JRE的平台上。但由于JRMP是专为Java对象制定的,因此,RMI对于用非Java语言开发的应用系统的支持不足。不能与用非Java语言书写的对象进行通信。
2.知识剖析
Java RMI与RPC的区别:
一:RPC 远程过程调用
RPC(Remote Procedure Call Protocol)远程过程调用协议,通过网络从远程计算机上请求调用某种服务。
一次RPC调用的过程大概有10步:
1.执行客户端调用语句,传送参数
2.调用本地系统发送网络消息
3.消息传送到远程主机
4.服务器得到消息并取得参数
5.根据调用请求以及参数执行远程过程(服务)
6.执行过程完毕,将结果返回服务器句柄
7.服务器句柄返回结果,调用远程主机的系统网络服务发送结果
8.消息传回本地主机
9.客户端句柄由本地主机的网络服务接收消息
10.客户端接收到调用语句返回的结果数据
二:RMI 远程方法调用
RMI:远程方法调用(Remote Method Invocation)。能够让在客户端Java虚拟机上的对象像调用本地对象一样调用服务端java 虚拟机中的对象上的方法。
RMI远程调用步骤:
1,客户调用客户端辅助对象stub上的方法
2,客户端辅助对象stub打包调用信息(变量,方法名),通过网络发送给服务端辅助对象skeleton
3,服务端辅助对象skeleton将客户端辅助对象发送来的信息解包,找出真正被调用的方法以及该方法所在对象
4,调用真正服务对象上的真正方法,并将结果返回给服务端辅助对象skeleton
5,服务端辅助对象将结果打包,发送给客户端辅助对象stub
6,客户端辅助对象将返回值解包,返回给调用者
7,客户获得返回值
三:RPC与RMI的区别
1:方法调用方式不同:
RMI中是通过在客户端的Stub对象作为远程接口进行远程方法的调用。每个远程方法都具有方法签名。如果一个方法在服务器上执行,但是没有相匹配的签名被添加到这个远程接口(stub)上,那么这个新方法就不能被RMI客户方所调用。
RPC中是通过网络服务协议向远程主机发送请求,请求包含了一个参数集和一个文本值,通常形成“classname.methodname(参数集)”的形式。RPC远程主机就去搜索与之相匹配的类和方法,找到后就执行方法并把结果编码,通过网络协议发回。
2:适用语言范围不同:
RMI只用于Java;
RPC是网络服务协议,与操作系统和语言无关。
3:调用结果的返回形式不同:
Java是面向对象的,所以RMI的调用结果可以是对象类型或者基本数据类型;
RMI的结果统一由外部数据表示 (External Data Representation, XDR) 语言表示,这种语言抽象了字节序类和数据类型结构之间的差异。
RMI有什么优点:
1、面向对象:
RMI可将完整的对象作为参数和返回值进行传递,而不仅仅是预定义的数据类型。
也就是说,可以将类似Java哈西表这样的复杂类型作为一个参数进行传递。
2、可移动属性:
RMI可将属性从客户机移动到服务器,或者从服务器移动到客户机。
3、设计方式:
对象传递功能使您可以在分布式计算中充分利用面向对象技术的强大功能,如二层和三层结构系统。
如果用户能够传递属性,那么就可以在自己的解决方案中使用面向对象的设计方式。
所有面向对象的设计方式无不依靠不同的属性来发挥功能,如果不能传递完整的对象——包括实现和类型
——就会失去设计方式上所提供的优点。
4、安全性:
RMI使用Java内置的安全机制保证下载执行程序时用户系统的安全。
RMI使用专门为保护系统免遭恶意小程序侵害而设计的安全管理程序。
5、便于编写和使用
RMI使得Java远程服务程序和访问这些服务程序的Java客户程序的编写工作变得轻松、简单。
远程接口实际上就是Java接口。
RMI有什么劣势:
RMI的局限性之一是RMI是Java语言的远程调用,两端的程序语言必须是Java实现,对于不同语言间的通讯可以考虑用Web Service或者公用对象请求代理体系(CORBA)来实现。
对服务器的IP地址和端口依赖很紧密,但是在开发的时候不知道将来的服务器IP和端口如何,但是客户端程序依赖这个IP和端口。这也是RMI的局限性之一。这个问题有两种解决途径:一是通过DNS来解决,二是通过封装将IP暴露到程序代码之外。
3.常见问题
1. springRMI指定的两个端口是什么?
2. rmi为什么要抛RemoteException:
4.解决方案
(1)注册端口:registryPort 注册端口是RMI注册远程服务的端口。
服务端口:servicePort RMI的通讯需要的传送数据的端口。如果没有设置servicePort,则使用随机端口。
(2)由于远程方法的本质还是网络通信,只不过隐藏了底层实现,网络通信是经常会出现异常的,所以接口的所有方法都要抛出RemoteException来说明此方法是有风险的。
5.编码实战
6.扩展思考
Tuscany RMI端口问题:
RMI之所以使用的范围受限制主要有两方面原因,其一:必须要是java,平台的异构性受到限制;其二:穿越防火墙不方便。这里主要谈谈RMI如何通过固定分配端口来穿越防火墙。
RMI穿越防火墙不方便主要是因为除了RMI服务注册的端口(默认1099)外,与RMI的通讯还需要另外的端口来传送数据,而另外的端口是随机分配的,所以要想RMI的客户能通过防火墙来与RMI服务通讯,
第一种方法:
需要能让随机分配的端口固定下来,具体做法如下:
如果是spring+rmi,可以通过spring bean方式来指定两个端口,但是tuscany不行,需要自己写类来完成。
通过比对spring 的指定端口的源码发现
<bean id = "rmiService" class = "org.springframework.remoting.rmi.RmiRegistryFactoryBean" >
在这个类里
通过这个接口配置服务器相关配置
在RMIServerSocketFactory里 发现设置端口的接口,百度发现就是这个东西
继承它的实现,并重写
public class SMRMISocket extends RMISocketFactory {
private static Logger logger = LoggerFactory.getLogger(SMRMISocket.class);
@Override
public Socket createSocket(String host, int port) throws IOException {
return new Socket(host,port);
}
@Override
public ServerSocket createServerSocket(int port) throws IOException {
if (port == 0) {
port = 8089; //不指定就随机分配了
logger.info("port服务端端口号:" + port);
}
logger.info("服务端端口号:" + port);
return new ServerSocket(port);
}
}
在main里调用:
RMISocketFactory.setSocketFactory(new SMRMISocket());
这样的话RMI分配的端口就被固定了,防火墙只需要打开1099和8089端口即可。
第二种方法:
在阿里云中开放所有的端口,这样不管rmi传送数据的是哪个端口都可以通过。
7.参考文献
https://www.cnblogs.com/ygj0930/p/6542811.html
https://blog.csdn.net/ajun_studio/article/details/7777167
https://blog.csdn.net/solidwang/article/details/17371973
8.更多讨论
Q1:提问人:王耀其:
Tuscany内置容器是什么?
A1:回答人(何爽):
Tuscany内置的容器,并非是Jetty,而是Geronimo,Geronimo拥有管理web容器的能力,包括jetty,tomcat,MQ等等;
Q2:提问人:周宏浩
Tuscany-rmi端口固定有什么限制么?
A2:回答人(何爽):
Tuscany-rmi的端口固定可以随机固定端口,但注意不要端口冲突,一般10000之后的端口都可以随便使用。
Q3:提问人:周宏浩
spring-rmi和Tuscany-rmi有什么区别?
A3:回答人(何爽):
没有什么太大的区别,它们的实现机制都是一样的,推荐使用spring-rmi,因为它大部分已经封装好了,我们用时会比较方便,且Tuscany-rmi毕竟出来的时间已经很久了,切一直没有更新,现在处于无维护现状。
9.鸣谢
感谢王耀其,常雷雷,此教程是在他们之前技术分享的基础上完善而成。
10.结束语
今天的分享就到这里啦,欢迎大家点赞、转发、留言、拍砖~
更多内容,可以加入IT交流群565734203与大家一起讨论交流
这里是技能树·IT修真院:https://www.jnshu.com,初学者转行到互联网的聚集地