Skip to content

开发 RPC 框架

字数: 0 字 时长: 0 分钟

什么是 RPC ?

RPC (Remote Procedure Call,远程过程调用)是一种计算机通信协议,它允许程序能够像调用本地方法一样调用远程服务器上的方法或函数

第一次听到 RPC 这个概念的时候是在学习 Kubernetes 的时候,当时官方文档提到底层采用 RPC 进行通信.当时我也不确定 RPC 具体是什么,直到遇到了鱼皮大佬的开源 RPC 项目,才对 RPC 框架有更深的认识,也开始第一次做这种轮子类项目。

项目开源地址:https://gitee.com/ttdxg/t-rpc

效果演示

第一次接触 RPC 概念可能还是很难理解 像调用本地方法一样去调用远程方法 ,下面我演示我开发的 RPC 框架效果:

1. 创建 example-common 模块作为公共的 api 暴露模块,用来暴露接口和实体类

demo1.webp

2. 创建 springboot-provider 作为服务提供者,提供接口的具体实现

demo4.webp

  • 只需要引入 example-commonroc-starter 模块,在启动类上添加 @EnableRpc 注解

demo2.webp

  • 然后接口实现类上添加 @RpcService 注解表明这是 RPC 接口实现类

demo3.webp

3. 创建 springboot-consumer 作为服务消费者,调用服务提供者的接口

demo5.webp

  • 只需要使用 @RpcReference 注入远程服务,即可当作本地方法一样调用

demo6.webp

4. 分别启动服务提供者和消费者,进行测试访问

可以发现 consumer 模块成功访问到了 provider 模块的远程方法

demo7.webp

可以发现有了 RPC 框架之后,客户端只需要几个注解就能将远程方法当作本地方法一样进行调用。

框架原理

我们来梳理一下本地调用一个远程方法需要如何实现:

1. 客户端代理

客户端调用 userService.getUser(user) 方法实际是根本不知道userService接口的getUser方法的具体实现的。

这里需要代理本地接口,拦截方法调用,封装请求对象

2. 注册中心

客户端代理拦截了方法调用,但是只知道 userService.getUser(user)(接口、方法名、参数),并不知道实现类在哪里。

那么此时需要去注册中心获取接口的实现类相关信息(服务提供者启动时就需要将提供的服务注册到注册中心)

3. 网络传输

代理通过注册中心知道了服务提供者地址了,此时需要发送请求给服务提供者,请求中需要携带接口、方法名、参数等信息

涉及到网络传输就要考虑通信协议(Http/WebSocket/TCP),而且发送请求涉及到负载均衡策略,确定发送给哪个服务实例。

4. 序列化层

请求参数在网络传输过程中需要序列化,服务提供者收到请求参数后,需要反序列化

5. web 服务器

服务提供者需要选择 Web 服务器用以接收消费者的请求,并根据请求参数选择请求处理器进行处理(找到本地服务实现,再通过网络传输返回结果给消费者)

rpc 远程调用流程 RPC流程.webp

技术选型

鱼皮选择 Etcd(Kubernetes 就是采用 Etcd 作为底层的元数据存储系统)作为注册中心;Vert.x 作为网络框架。

而我本身是为了学习才开发这个 RPC 框架,为了更加深对 RedisNetty 的实战应用,我选择 Redis 来实现注册中心、Netty 作为网络框架。

总之,通过开发这个 RPC 框架,可以对网络、序列化、代理、服务注册与发现、负载均衡、可扩展设计、starter 开发等知识有更深入的理解。

那么接下来就从 0 到 1 开始开发这个 RPC 框架吧!