RPC介绍

116 阅读3分钟

rpc能实现调用远程方法就跟调用本地(同一个项目中的方法)一样,发起调用请求的那一方叫做调用方,被调用的一方叫做服务提供方

发起远程调用的核心是网络通信,那我们手动实现rpc框架的核心就是封装通信细节,本小节我们主要和大家一起来思考整个调用过程中的一些流程和细节:

1、传输协议:既然 yrpc 存在的核心目的是为了实现远程调用,既然是远程调用那肯定就需要通过网络来传输数据,并且 yrpc 常用于业务系统之间的数据交互,需要保证其可靠性,所以 yrpc 一般默认采用 TCP 来传输。事实上。我们常用的 HTTP 协议也是建立在 TCP 之上的。选择tcp的核心原因还是因为他的效率要比很多应用层协议高很多。

2、封装一个可用的协议:选择了合适的传输层协议之后,我们需要基于此建立一个我们自己的通用协议,和http一样需要封装自己的应用层协议,详细的内容会在后边的课程里详细介绍。

3、序列化:网络传输的数据必须是二进制数据,但调用方请求的出入参数都是对象。对象是肯定没法直接在网络中传输的,需要提前把它转成可传输的二进制,并且要求转换算法是可逆的,这个过程我们一般叫做“序列化”。

4、压缩:如果我们觉得序列化后的字节数组体积比较大,我们还可以对他进行压缩,压缩后的字节数组体积更小,能在传输的过程中更加节省带宽和内存。

到这里,一个简单版本的 yrpc 框架就实现了。我把整个流程都画出来了,供你参考:

1679382066545

那上述几个流程就组成了一个完整的 rpc 吗?

在我看来,还缺点东西。因为对于研发人员来说,这样做要掌握太多的 rpc 底层细节,需要手动写代码去构造请求、调用序列化,并进行网络调用,整个 API 非常不友好。

那我们有什么办法来简化 API,屏蔽掉 rpc 细节,让使用方只需要关注业务接口,像调用本地一样来调用远程呢?

如果你了解 Spring,一定对其 AOP 技术很佩服,其核心是采用动态代理的技术,通过字节码增强对方法进行拦截增强,以便于增加需要的额外处理逻辑。其实这个技术也可以应用到 rpc 场景来解决我们刚才面临的问题。

由服务提供者给出业务接口声明,在调用方的程序里面,rpc 框架根据调用的服务接口提前生成动态代理实现类,并通过依赖注入等技术注入到声明了该接口的相关业务逻辑里面。该代理实现类会拦截所有的方法调用,在提供的方法处理逻辑里面完成一整套的远程调用,并把远程调用结果返回给调用方,这样调用方在调用远程方法的时候就获得了像调用本地接口一样的体验。