RPC原理

让我们回到 RPC 最初的目的,要想实现调用远程方法像调用本地方法一样简单,至少要解决如下问题:

  1. 如何获取可用的远程服务器
  2. 如何表示数据
  3. 如何传递数据
  4. 服务端如何确定并调用目标方法

架构图.png

图中服务端启动时将自己的服务节点信息注册到注册中心,客户端调用远程方法时会订阅注册中心中的可用服务节点信息,拿到可用服务节点之后远程调用方法,当注册中心中的可用服务节点发生变化时会通知客户端,避免客户端继续调用已经失效的节点。

调用图.png

  1. 客户端模块代理所有远程方法的调用
  2. 将目标服务、目标方法、调用目标方法的参数等必要信息序列化
  3. 序列化之后的数据包进一步压缩,压缩后的数据包通过网络通信传输到目标服务节点
  4. 服务节点将接受到的数据包进行解压
  5. 解压后的数据包反序列化成目标服务、目标方法、目标方法的调用参数
  6. 通过服务端代理调用目标方法获取结果,结果同样需要序列化、压缩然后回传给客户端

RPC实现细节

服务注册与发现

系统选用 Zookeeper 作为注册中心, ZooKeeper 将数据保存在内存中,性能很高。 在少的场景中尤其适用,因为操作会导致所有的服务器间同步状态。服务注册与发现是典型的少的协调服务场景。 Zookeeper 是一个典型的CP系统,在服务选举或者集群半数机器宕机时是不可用状态,相对于服务发现中主流的AP系统来说,可用性稍低,但是用于理解RPC的实现,也是绰绰有余。

ZooKeeper节点

  • 持久节点( PERSISENT ):一旦创建,除非主动调用删除操作,否则一直持久化存储。
  • 临时节点( EPHEMERAL ):与客户端会话绑定,客户端会话失效,这个客户端所创建的所有临时节点都会被删除除。
  • 节点顺序( SEQUENTIAL ):创建子节点时,如果设置SEQUENTIAL属性,则会自动在节点名后追加一个整形数字,上限是整形的最大值;同一目录下共享顺序,例如(/a0000000001,/b0000000002,/c0000000003,/test0000000004)。

easy-rpc框架调用流程:

架构图

  • 代理层:负责对底层调用细节的封装;
  • 链路层:负责执行一些自定义的过滤链路,可以供后期二次扩展;
  • 路由层:负责在集群目标服务中的调用筛选策略;
  • 协议层:负责请求数据的转码封装等作用;
  • 注册中心:关注服务的上下线,以及一些权重,配置动态调整等功能;
  • 容错层:当服务调用出现失败之后需要有容错层的兜底辅助;