RPC实战与核心原理之网络通信

架构设计:涉及一个灵活的RPC框架

回顾

RPC的通信原理及RPC中各个功能组件的作用

  • RPC就是把拦截到的方法参数,转成可以在网络中传输的二进制,并保证服务提供方能正确还原出语义,最终实现想调用本地一样的调用远程的目的

RPC架构

功能模块

  • 传输模块

    • 考虑到传输的可靠性,一般默认采用TCP协议;为了屏蔽网络传输的复杂性,需要封装一个单独的数据传输模块用来收发二进制数据,这个单独的模块叫做传输模块
  • 协议模块

    • 序列化过程

      • 用户请求的时候是基于方法调用,方法出入参数都是对象数据,需要提前将对象数据转换为可传输的二进制,这就是序列化过程
    • 协议封装

      • 光把方法调用参数的二进制数据传输到服务提供方是不够的,需要在方法调用参数的二进制后面增加“断句”符号来分隔不同的请求,在两个“断句”符号中间放的内容就是请求的二进制数据,这个过程叫做协议封装
    • 压缩功能

  • Bootstrap模块

    • 细节对研发人员进行屏蔽,让他们感觉不到本地调用和远程调用的区别。假设有用到 Spring 的话,我们希望 RPC 能让我们把一个 RPC 接口定义成一个 Spring Bean,并且这个 Bean 也会统一被 Spring Bean Factory 管理,可以在项目中通过 Spring 依赖注入到方式引用。这是 RPC 调用的入口,我们一般叫做 Bootstrap 模块。

集群

所谓集群能力,就是针对同一个接口有着多个服务提供者,但这多个服务提供者对于我们的调用方来说是透明的,所以在 RPC 里面我们还需要给调用方找到所有的服务提供方,并需要在 RPC 里面维护好接口跟服务提供者地址的关系,这样调用方在发起请求的时候才能快速地找到对应的接收地址,这就是我们常说的“服务发现”。

  • 服务发现只是解决了接口和服务提供方地址映射关系的查找问题

插件化架构

可以将每个功能点抽象成一个接口,将这个接口作为插件的契约,然后把这个功能的接口与功能的实现分离,并提供接口的默认实现

在 Java 里面,JDK 有自带的 SPI(Service Provider Interface)服务发现机制,它可以动态地为某个接口寻找服务实现。使用 SPI 机制需要在 Classpath 下的 META-INF/services 目录里创建一个以服务接口命名的文件,这个文件里的内容就是这个接口的具体实现类。

加上了插件功能之后,我们的 RPC 框架就包含了两大核心体系——核心功能体系与插件体系,

  • 将每个功能点抽象成一个接口,将这个接口作为插件的契约,然后把这个功能的接口与功能的实现分离并提供接口的默认实现。
  • 首先它的可扩展性很好,实现了开闭原则,用户可以非常方便地通过插件扩展实现自己的功能,而且不需要修改核心功能的本身;其次就是保持了核心包的精简,依赖外部包少,这样可以有效减少开发人员引入 RPC 导致的包版本冲突问题。
posted @ 2022-02-13 17:13  牛犁heart  阅读(245)  评论(0编辑  收藏  举报