RPC原理
让我们回到 RPC 最初的目的,要想实现调用远程方法像调用本地方法一样简单,至少要解决如下问题:
- 如何获取可用的远程服务器
- 如何表示数据
- 如何传递数据
- 服务端如何确定并调用目标方法
图中服务端启动时将自己的服务节点信息注册到注册中心,客户端调用远程方法时会订阅注册中心中的可用服务节点信息,拿到可用服务节点之后远程调用方法,当注册中心中的可用服务节点发生变化时会通知客户端,避免客户端继续调用已经失效的节点。
- 客户端模块代理所有远程方法的调用
- 将目标服务、目标方法、调用目标方法的参数等必要信息序列化
- 序列化之后的数据包进一步压缩,压缩后的数据包通过网络通信传输到目标服务节点
- 服务节点将接受到的数据包进行解压
- 解压后的数据包反序列化成目标服务、目标方法、目标方法的调用参数
- 通过服务端代理调用目标方法获取结果,结果同样需要序列化、压缩然后回传给客户端
RPC实现细节
服务注册与发现
系统选用 Zookeeper 作为注册中心, ZooKeeper 将数据保存在内存中,性能很高。 在读
多写
少的场景中尤其适用,因为写
操作会导致所有的服务器间同步状态。服务注册与发现是典型的读
多写
少的协调服务场景。 Zookeeper 是一个典型的CP系统,在服务选举或者集群半数机器宕机时是不可用状态,相对于服务发现中主流的AP系统来说,可用性稍低,但是用于理解RPC的实现,也是绰绰有余。
ZooKeeper节点
- 持久节点( PERSISENT ):一旦创建,除非主动调用删除操作,否则一直持久化存储。
- 临时节点( EPHEMERAL ):与客户端会话绑定,客户端会话失效,这个客户端所创建的所有临时节点都会被删除除。
- 节点顺序( SEQUENTIAL ):创建子节点时,如果设置SEQUENTIAL属性,则会自动在节点名后追加一个整形数字,上限是整形的最大值;同一目录下共享顺序,例如(/a0000000001,/b0000000002,/c0000000003,/test0000000004)。
easy-rpc
框架调用流程:
- 代理层:负责对底层调用细节的封装;
- 链路层:负责执行一些自定义的过滤链路,可以供后期二次扩展;
- 路由层:负责在集群目标服务中的调用筛选策略;
- 协议层:负责请求数据的转码封装等作用;
- 注册中心:关注服务的上下线,以及一些权重,配置动态调整等功能;
- 容错层:当服务调用出现失败之后需要有容错层的兜底辅助;