分布式消息通信框架RMI原理分析

对着背影说爱祢 提交于 2019-12-07 17:31:22

什么是RPC

  • RPC(Remote Procedure Call,远程过程调用)
  • 一般用来实现部署在不同机器上系统之间方法调用
    • 使得程序能够像访问本地系统资源一样,通过网络传输去访问远端系统资源;(!!!)
    • 对于客户端来说, 传输层使用什么协议,序列化、反序列化都是透明的

了解 Java RMI

  • RMI 全称是remote method invocation – 远程方法调用,
  • 一种用于远程过程调用的应用程序编程接口,是纯java 的网络分布式应用系统的核心解决方案之一。
  • RMI 目前使用Java 远程消息交换协议JRMP(Java Remote Messageing Protocol) 进行通信,
  • 由于JRMP 是专为Java对象制定的,是分布式应用系统的百分之百纯java 解决方案,
  • 用Java RMI 开发的应用系统可以部署在任何支持JRE的平台上

Java RMI 代码实践

  • 远程对象必须实现UnicastRemoteObject
  • 这样才能保证客户端访问获得远程对象时,该远程对象把自身的一个拷贝Socket 形式传输给客户端
  • 客户端获得的拷贝称为“stub” ,
  • 而服务器端本身已经存在的远程对象成为“skeleton”,
  • 此时客户端的stub 是客户端的一个代理,用于与服务器端进行通信
  • 而skeleton 是服务端的一个代理
  • 用于接收客户端的请求之后调用远程方法来响应客户端的请求

Java RMI 源码分析

  • 远程对象发布

远程引用层

一步步解读源码

  • 发布远程对象
    • 看到上面的类图可以知道,这个地方会发布两个远程对象,一个是RegistryImpl、另外一个是我们自己写的RMI 实现类对象

LocateRegistry.createRegistry(1099);
  • 如果服务端指定的端口是1099 并且系统开启了安全管理器,那么就可以在限定的权限集内绕过系统的安全校验。
  • 这里纯粹是为了提高效率, 真正的逻辑在this.setup(newUnicastServerRef())这个方法里面

  • 有一个问题为什么断点进去的时候,会重复接收到多个请求
    • 这是TCP协议特性
    • TCP为了保证不发生丢包,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。
    • 然后接收端实体对已成功收到的包发回一个相应的确认(ACK);
    • 如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据包就被假设为已丢失将会被进行重传。
    • TCP用一个校验和函数来检验数据是否有错误;在发送和接收时都要计算校验和。
  • 这个Target 对象基本上包含了全部的信息,等待TCP 调用。
    • 包装实际对象,并将其曝露在TCP端口上,等待客户端调用
    • 用skeleton、stub、UnicastServerRef 对象、id 和一个boolean 值构造了一个Target 对象
  • LiveRef 与TCP 通信的类
  • RegistryImpl extends RemoteServer implements Registry
    • Skeleton
    • private Hashtable<String, Remote> bindings = new Hashtable(101);
    • 这个bindings 绑定服务(注册中心)
    • Naming.rebind("rmi://127.0.0.1/Hello",helloService); //注册中心 key - value
  • RegistryImpl_Stub
    • stub
  • LocateRegistry
  • UnicastServerRef
    • 内部引用了LiveRef
  • UnicastRemoteObject
    • 字面意思(单播远程对象)
  • RemoteRef
  • Remote
  • TCPTransport
    • 调用TCPTransport 的listen()方法,listen()方法创建了一个ServerSocket,并且启动了一条线程等待客户端的请求。

  • Stub和Skeleton:
    • 这两个的身份是一致的,都是作为代理的存在。
    • 客户端的称作Stub,服务端的称作Skeleton。
    • 要做到对程序员屏蔽远程方法调用的细节,这两个代理是必不可少的,包括网络连接等细节。
  • Registry:顾名思义,可以认为Registry是一个“注册重心”,提供了服务名到服务的映射。
    • 如果没有它,意味着客户端需要记住每个服务所在的端口号,这种设计显然是不优雅的。

  • 看源码要看到什么程度:“看到你觉得你能说服自己就可以了”
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!