首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >手搓RPC框架系列(一):基于架构设计原则的RPC基础架构设计

手搓RPC框架系列(一):基于架构设计原则的RPC基础架构设计

原创
作者头像
六边形架构
发布2025-12-16 20:24:35
发布2025-12-16 20:24:35
980
举报
文章被收录于专栏:系统架构系统架构

文 / Kenyon,资深软件架构师,15年软件开发和技术管理经验,从程序员做到企业技术高管,专注技术管理、架构设计、AI技术应用和落地。

由于公众号推流的原因,请在关注页右上角加星标,这样才能及时收到新文章的推送。

引言

在上两篇文章中,我们深入探讨了架构设计的核心原则、方法和模式,从SOLID基本设计原则到分布式系统的CAP定理,这些都是构建高质量系统的基础。今天,我们将把这些理论知识应用到实践中,让我带大家从零开始构建一个类似Dubbo的RPC框架。

Dubbo架构图
Dubbo架构图

RPC(Remote Procedure Call,远程过程调用)是分布式系统中服务之间通信最核心的机制,它允许一个进程去调用一个可以是远在天边的另外一个进程中的函数,虽然相隔甚远,但是调用的时候就像调用本地函数一样简单。Dubbo作为国内最流行的RPC框架之一,它的设计理念和架构的实现充分体现了我们之前学习的各种架构设计原则。

一、核心需求分析

在开始设计之前,我们先明确一下我们的这个RPC框架的核心需求,根据YAGNI原则的要求,我们只实现当前必要的功能,主要是下面的5点:

  1. 具备远程调用的能力:允许客户端像调用本地方法一样调用远程的服务实例
  2. 可以进行服务注册与发现:客户端能够自动发现可供调用的服务实例,无需手动去配置
  3. 具备负载均衡的能力:客户端或者服务端可以根据负载均衡的策略将请求分发到多个实例上面,提高系统可用性和性能
  4. 序列化与反序列化:客户端可以将对象转换为可以进行网络传输的格式,服务端再把对应的格式转换为对象,并且支持跨语言调用
  5. 可以利用网络进行通信:处理底层网络传输,支持不同的协议(如TCP、HTTP)

二、基于架构设计原则的RPC架构设计

1. 基于SOLID原则的核心组件设计

单一职责原则(SRP)

因为远程调用是RPC框架的核心功能,所以我们将RPC框架拆分为多个职责单一的组件:

  • Proxy层:主要是负责将客户端的本地方法调用转换为远程调用
  • Registry层:主要负责服务的注册与发现,服务端可以在上面注册自己的服务实例,客户端可以通过注册中心发现可用的服务实例
  • LoadBalance层:主要负责服务调用时的负载均衡策略,将客户端的请求分发到多个服务实例上面,提高系统的可用性和性能
  • Serializer层:主要负责序列化与反序列化,将对象转换为网络传输格式,支持跨语言调用
  • Transport层:负责网络通信,处理底层的网络传输,支持不同的协议(如TCP、HTTP等)
开闭原则(OCP)

通过抽象接口实现组件的可扩展性:

代码语言:java
复制
// 序列化接口,支持扩展不同的序列化方式(JSON、Protobuf等)
public interface Serializer {
    <T> byte[] serialize(T obj);
    <T> T deserialize(byte[] bytes, Class<T> clazz);
}

// 负载均衡接口,支持扩展不同的负载均衡策略(随机、轮询、一致性哈希等)
public interface LoadBalancer {
    InetSocketAddress select(List<InetSocketAddress> addresses);
}

// 其他组件的SRP也类似,都是负责单一的功能
依赖倒置原则(DIP)

高层的模块都不依赖底层模块的具体实现,全都依赖其抽象类或接口:

  • 比如我们在实现RPC框架核心模块的逻辑的时候,都是依赖Serializer、LoadBalancer、RegistryCenter等抽象接口
  • 像具体的实现类(如JsonSerializer、RandomLoadBalancer)都是依赖上面定义的这些接口

2. 基于通用设计原则的架构优化

高内聚低耦合
  • 每个组件内部的功能和实现逻辑都是紧密相关的(高内聚)
  • 组件之间通过接口来进行通信,尽量减少直接的依赖(低耦合)
  • 例如:Proxy层不可以直接依赖具体的Transport的实现,而是通过Transport的接口来进行通信
KISS原则(Keep It Simple, Stupid)
  • 初始的MVP版本只需要实现核心的功能就可以了,避免出现过度设计的情况
  • 接口的设计要简洁明了,减少不必要的参数和复杂的逻辑
  • 例如:服务注册只需要服务名称、地址和端口即可,客户端只需要知道服务名称即可调用
迪米特法则
  • 组件之间只与直接依赖的组件通信
  • 例如:客户端不需要知道服务注册中心的具体实现,只需要通过Registry接口调用即可

三、RPC框架的核心架构图

基于以上设计原则,我们可以画出RPC框架的核心架构图:

RPC框架架构图
RPC框架架构图

四、核心组件的详细设计

1. 服务代理(Service Proxy)

  • 该组件负责将客户端的本地方法调用转换为远程调用
  • 实现方式:JDK动态代理、CGLIB代理
  • 核心功能:
    • 拦截方法调用
    • 构建请求对象
    • 选择服务实例
    • 发送远程请求
    • 处理响应结果

2. 服务注册中心(Registry Center)

  • 该组件负责客户端和服务端的服务注册与发现
  • 实现方式:可以实现基于ZooKeeper、Nacos等注册中心来实现服务的注册与发现
  • 核心功能:
    • 服务注册:服务端将服务实例的信息注册到注册中心上面,主要的信息包括服务名称、地址和端口等信息
    • 服务发现:客户端从注册中心获取服务实例的列表,根据服务名称来选择需要调用的服务实例
    • 服务监听:监听服务实例的上下线变化,及时更新本地的服务实例列表,以免调用到已经下线的服务实例

3. 负载均衡(Load Balance)

  • 该组件负责将客户端的请求分发到服务端的实例上面进行处理,如果有多个实例的话,就可以根据指定的负载均衡算法来选择其中一个实例进行处理
  • 常见算法:
    • 随机算法(Random),在多个实例中随机选择一个进行处理
    • 轮询算法(Round Robin),按照服务端在注册中心注册时的顺序依次选择实例进行处理
    • 一致性哈希算法(Consistent Hash),根据请求的哈希值来选择实例进行处理,能够保持请求的一致性
    • 加权轮询算法(Weighted Round Robin),根据实例的权重来选择实例进行处理,权重高的实例会被更多的请求处理

4. 序列化(Serializer)

  • 该组件负责将请求和处理结果的对象转换成可以支持网络传输的格式
  • 常用序列化方式:
    • JSON:可读性好,支持跨语言处理
    • Protobuf:性能高,空间效率好
    • Hessian:Java原生支持,性能还算较好

5. 网络传输(Transport)

  • 该组件负责整个RPC框架底层的网络通信
  • 实现方式:
    • Netty:一个基于异步事件驱动的高性能网络通信框架
    • Bio:同步阻塞IO,一般不建议使用
    • Nio:同步非阻塞IO,性能较高,但是实现复杂
Dubbo服务调用整体流程图
Dubbo服务调用整体流程图

五、总结与下一步计划

在上文中,我们基于SOLID原则和通用设计原则,设计了一个类似Dubbo的RPC框架的基础架构。我们将RPC框架拆分为多个职责单一的组件,然后可以通过抽象接口的实现来扩展和替换这些组件,实现组件的可扩展性,并遵循了高内聚低耦合、KISS等设计原则。

在下一篇文章中,我们将进入实战阶段,实现RPC框架的核心功能,包括服务代理、序列化、网络通信等模块。


互动话题:你对RPC框架的设计有什么看法?你认为RPC框架中最重要的组件是什么?欢迎在评论区分享你的观点。

关于作者

Kenyon,资深软件架构师,15年的软件开发和技术管理经验,从程序员做到企业技术高管。多年企业数字化转型和软件架构设计经验,善于帮助企业构建高质量、可维护的软件系统,目前专注技术管理、架构设计、AI技术应用和落地;全网统一名称"六边形架构",欢迎关注交流。

原创不易,转载请联系授权,如果觉得有帮助,请点赞、收藏、转发三连支持!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 引言
  • 一、核心需求分析
  • 二、基于架构设计原则的RPC架构设计
    • 1. 基于SOLID原则的核心组件设计
      • 单一职责原则(SRP)
      • 开闭原则(OCP)
      • 依赖倒置原则(DIP)
    • 2. 基于通用设计原则的架构优化
      • 高内聚低耦合
      • KISS原则(Keep It Simple, Stupid)
      • 迪米特法则
  • 三、RPC框架的核心架构图
  • 四、核心组件的详细设计
    • 1. 服务代理(Service Proxy)
    • 2. 服务注册中心(Registry Center)
    • 3. 负载均衡(Load Balance)
    • 4. 序列化(Serializer)
    • 5. 网络传输(Transport)
  • 五、总结与下一步计划
  • 关于作者
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档