温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

手写一个RPC框架的方法教程

发布时间:2021-10-25 16:11:51 来源:亿速云 阅读:145 作者:iii 栏目:开发技术

本篇内容介绍了“手写一个RPC框架的方法教程”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成! 

介绍

当开发一个单体项目的时候,大家肯定都写过类似的代码。即服务提供方和服务调用方在一个服务中

public interface HelloService {     public String sayHello(String content); }
public class HelloServiceImpl implements HelloService {      @Override     public String sayHello(String content) {         return "hello, " + content;     } }
public class Test {      public static void main(String[] args) {         HelloService helloService = new HelloServiceImpl();         String msg = helloService.sayHello("world");         // hello world         System.out.println(msg);     } }

但是由于单体服务的诸多弊端,现在很多公司已经将不相关的功能拆分到不同的服务中。

如何像调用本地服务一样调用远程服务呢?这时就不得不提RPC框架了(Remote Procedure  Call,远程过程调用)。他帮我们屏蔽了网络通信,序列化等操作的实现,真正做到了调用远程服务和调用本地服务一样方便。

知名的RPC框架有Spring Cloud,阿里巴巴的Dubbo,Facebook的Thrift,Google grpc等

RPC的调用过程

手写一个RPC框架的方法教程

一个RPC调用的过程如下

  1. 鸿蒙官方战略合作共建——HarmonyOS技术社区

  2. 调用方发送请求后由代理类将调用的方法,参数组装成能进行网络传输的消息体

  3. 调用方将消息体发送到提供方

  4. 提供方将消息进行解码,得到调用的参数

  5. 提供方反射执行相应的方法,并将结果返回

下面我们就分析一下rpc框架是怎么实现的?有哪些地方可以扩展。为了让大家有一个更形象的认识,我写了一个github项目,由简到难实现了一个rpc框架,欢迎star

https://github.com/erlieStar/simple-rpc

生成代理类

前面我们说过,调用方执行方法后,实际上执行的是代理类的方法,代理类帮我们进行序列化和编解码操作。那么如何生成代理类呢?

我们看一下主流的做法。

Facebook的Thrift和Google的grpc都是定义一个schema文件,然后执行程序,帮你生成客户端代理类,以及接口。调用方直接用生成的代理类来请求,提供方继承生成的接口即可。

这种方式最大的优点就是能进行多语言通信,即一份schema文件可以生成Java程序,也可以生成Python程序。调用方是Java程序,提供方是Python程序都能正常进行通讯。而且是二进制协议,通讯效率比较高。

在Java中生成代理类的方式有如下几种

  1. 鸿蒙官方战略合作共建——HarmonyOS技术社区

  2. JDK动态代理(实现InvocationHandler接口)

  3. 字节码操作类库(如cglib,Javassist)

在Dubbo中提供了2种生成代理类的方式,jdk动态代理和Javassist,默认是javassist,至于原因吗?当然是javassist的效率更高

协议

为什么需要协议这个东西呢?Spring Cloud是通过Http协议来进行通讯的,那么Dubbo是通过哪种协议来进行通讯的?

为什么需要协议这个东西?

因为数据是以二进制的形式在网络中传输中,RPC的请求数据并不是以一个整体发送到提供方的,而是可能被拆分成多个数据包发送出去,那提供方怎么识别数据呢?

例如一个文本ABCDEF,提供方有可能依次收到的数据为ABC DEF,也有可能为AB CD EF。提供方该怎么处理这些数据呢?

简单啊,定个规则就可以了。这个规则可以有很多种,这里举3个例子

  1. 鸿蒙官方战略合作共建——HarmonyOS技术社区

  2. 定长协议,协议内容长度固定,如读取到50个byte就开始decode操作,可以参考Netty的FixedLengthFrameDecoder

  3. 特殊结束符,定义一个消息结束的分隔符,如读到\n,表示一个数据读取完毕了,没有读到就一直读,可以参考Netty的DelimiterBasedFrameDecoder

  4. 变长协议(协议头+协议体),用一个定长来表示消息体的长度,剩下的内容为消息体,如果你愿意的话,协议头还会放一些常用的属性,Http协议的Header就是协议头,如content-type,content-length等。可以参考Netty的DelimiterBasedFrameDecoder

Dubbo通过自定义协议来进行通讯,协议头格式如下

手写一个RPC框架的方法教程

每个位代表的含义如下

手写一个RPC框架的方法教程

Dubbo为什么要自定义协议,而不用现成的Http协议?

最主要的原因就是自定义协议可以提高性能

Http协议的请求包比较大,有很多无用的内容。自定义协议可以精简很多内容

Http协议是无状态的,每次都要重新建立连接,响应完毕后将连接关闭

序列化

协议头的内容是通过位来表示的,协议体在应用程序中则会被封装成对象,如Dubbo将请求封装成Request,将响应封装成Response

手写一个RPC框架的方法教程

前面我们说过网络传输的数据必须是二进制数据,但调用方的入参和提供方的返回值都是对象,因此需要序列化和反序列化的过程

序列化的方式有如下几种

  1. 鸿蒙官方战略合作共建——HarmonyOS技术社区

  2. JDK原生序列化

  3. JSON

  4. Protobuf

  5. Kryo

  6. Hessian2

  7. MessagePack

我们选择序列化的方式时,主要考虑如下几个因素

  1. 鸿蒙官方战略合作共建——HarmonyOS技术社区

  2. 效率

  3. 空间开销

  4. 通用性和兼容性

  5. 安全性

通讯

常见的IO模型有如下四种

  1. 鸿蒙官方战略合作共建——HarmonyOS技术社区

  2. 同步阻塞IO(Blocking IO)

  3. 同步非阻塞IO(Non-blocking IO)

  4. IO多路复用(IO Multiplexing)

  5. 异步IO(Asynchronous IO)

因为RPC一般用在高并发的场景下,因此我们选择IO多路复用这种模型,Netty的IO多路复用基于Reactor开发模式来实现,后续的文章我会分析一下这种开发模式是如何支持高并发的

注册中心

注册中心的作用和电话簿类似。保存了服务名称和具体的服务地址之间的映射关系,当我们想和某个服务进行通信时,只需要根据服务名就能查到服务的地址。

更重要的是这个电话簿是动态的,当某个服务的地址改变时,电话簿上的地址就会改变,当某个服务不可用时,电话簿上的地址就会消失

这个动态的电话簿就是注册中心。

注册中心的实现方式有很多种,Zookeeper,Redis,Nocas等都可以实现

介绍一下用Zookeeper实现注册中心的方式

zookeeper有两种类型的节点,持久节点和临时节点

当我们往zookeeper上注册服务的时候,用的是临时节点,这样当服务断开时,节点能被删除

节点类型解释
持久节点将节点创建为持久节点,数据会一直存储在zookeeper服务器上,即使创建该节点的客户端与服务端的会话关闭了,该节点依然不会被删除
持久顺序节点在持久节点的基础上增加了节点有序的特性
临时节点将节点创建为临时节点,数据不会一直存储在zookeeper服务器上,当创建该临时节点的客户端会话关闭时,该节点在相应的zookeeper服务器上被删除
临时顺序节点在临时节点的基础上增加了节点有序的特性

注册中心全部挂掉该怎么通信?

当一台zookeeper挂掉后,会自动切换到另一个zookeeper。全部挂掉也没有关系,因为dubbo把映射关系保存了一份在本地,这个映射关系可以保存在Map中,也可以保存在文件中

新的服务注册到注册中心,本地缓存会更新吗?

注册了监听的话,当然会更新啊。当被监听的节点或者子节点发生变化的时候,会将相应的内容推送给监听的客户端,你就可以更新本地的缓存了

Zookeeper中的事件如下

手写一个RPC框架的方法教程

你可以把这个监听理解为分布式的观察者模式

“手写一个RPC框架的方法教程”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI