设计一个简单的RPC

RPC三大要点

RPC全称是Remote Procedure Call,远程过程调用。也就是调用其他机器的方法。

我们可以自己想一下要怎么实现去调用其他机器的方法。

首先我们需要知道去哪里调用我们需要的服务。

因为服务端可能提供了很多个远程服务,也有可能多个进程部署在一个机器,为了防止端口冲突,往往使用随机端口,那我们要怎么知道访问哪个端口呢?这就涉及到服务发现的问题。

然后是如何传递参数呢?

如果有两个参数,要先传第一个还是第二个?TCP一端发送出去的数据,另外一端不能全部读取,怎么才算读完?还有一个类里面有各种数据,这些数据要怎么表示?这就需要有一个统一的方案,称之为协议约定问题

最后其实就是传输问题,因为我们远程调用肯定需要解决网络问题,如果发生了错误、重传、丢包、性能等问题怎么办?

下面来看一下各个要点的实现。

协议约定

自定义一个RPC协议的话,可以把它涉及成协议头和协议体,协议头包括协议版本,消息id标识这次rpc请求,消息类型,序列化方式等等,协议体由请求接口和参数构成,长度是可变的。

这里的参数,因为要通过网络传输,所以肯定不能使用UFT-8这类的编码,我们都应该转化成二进制后再传输,所以这里涉及到了序列化。

序列化

常用的序列化包括jdk原生序列化,hessian,protobuf(google使用的)等等。

选择序列化方式要从哪些方面考虑呢?

  • 首先要保证安全性。

  • 然后很重要的是通用性和兼容性,因为要考虑是否支持比较多的对象类型,是否跨平台、跨语言的,是否很多人使用并且踩过坑了。

  • 其次才考虑性能,效率和开销。

综合比较,我们首选的还是hessian和protobuf。

那么,序列化在使用时我们还需要注意什么问题吗?

首先要避免构造复杂的对象,因为越复杂的对象,在序列化和反序列化过程中就越容易出错

还要避免对象过于庞大,数据太大会很耗时的。

避免使用序列化不支持的类作为入参。比如hessian框架,他不支持LinkedHashMap、LinkedHashSet,避免使用第三方集合,尽量选择原生的、常用的集合类,如HashMap,ArrayList。

还要避免对象有复杂的继承关系,因为父类的属性也会被序列化,造成对象复杂且庞大,既影响性能,也容易出问题。

像dubbo中默认的RPC协议就是 Hessian2协议,Hessian2协议是自描述的,只要拿到二进制数据,根据本身的规则,就能解析出来,不需要另外的协议。

服务发现

服务发现是使用注册中心实现的,当一个应用启动之后,就向服务中心注册自己的服务,调用方先去注册中心找到要调用的服务,再去发起请求。

像Dubbo 会从注册中心获取服务端的列表,根据路由规则和负载均衡规则,在多个服务端中选择一个最合适的服务端进行调用。

传输问题

有很多的优秀的网络框架可以使用,在 Dubbo 里面,使用了 Netty 的网络传输框架。

如何设计RPC框架

这里我们来设计一个简单的rpc框架。首先,正如前面所说,我们需要一个注册中心,这个注册中心我们可以用zk,也可以自己做一个简单的注册中心。

这个注册中心用什么作用呢?前面我们介绍是用来注册自己的服务的,我们这里可以简单一点,我们可以自己配置自己项目的访问地址,配置发布的服务名称,bean的名称,方法名称。这样就完成了一个服务的注册。通过访问路径,可以找到服务所在的机器,然后通过bean的名称,方法的名称,可以找到具体的业务逻辑实现。

所以整个过程就是,先在注册中心注册好自己的服务。然后调用方根据服务名称获取注册中心的服务提供者的访问地址,这样就知道要访问哪台机器了。

之后,我们统一使用一个方法来调用rpc,这里就叫做execute(),这个方法传入的对象里面包括服务名称,参数的值。在调用execute()的时候,其实有用一个代理类去实现具体的网络请求。这里我们使用hessian序列化,将服务名称和参数通过网络框架传过去。

然后是服务提供端,收到了这个数据后,解析出数据,获取到服务名称,和参数。再去注册中心获取该服务的配置,之前配置了bean的名称,根据这个bean的名称去spring容器中获取bean,再通过方法名,使用反射去调用该方法,得到结果,再通过网络IO返回结果。

到这里,这个rpc调用就结束了,当然一个完整的rpc框架应该还包括限流、降级、限权等等功能,有机会再去研究。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值