这是一个基于Java的手写RPC框架项目,用于分布式系统中不同服务间通信。项目主要包含四个核心模块:
common
:定义通用类和接口。consumer
:服务消费者,通过 ServiceProxyFactory 创建代理对象发起远程调用。provider
:服务提供者,将服务本地注册到 LocalRegistry,启动 HTTP 服务器监听端口并处理请求。lzz-rpc-core
:框架核心模块,包含序列化器、代理、本地注册中心和 HTTP 服务器等功能。
主要内容:
- RPC框架中需要维护一个全局的配置对象。在某个Provider引入 RPC 框架的项目启动时,从配置文件application.properties(若没有则使用默认配置)中读取配置并创建全局配置对象实例(使用双检锁单例模式),之后就可以集中地从这个对象中获取配置信息,而不用每次加载配置时再重新读取配置、并创建新的对象,减少了性能开销。
- Consumer在配置文件中设置mock=true,RPC框架通过工厂模式给服务接口创建Mock代理对象,即可通过动态代理即可实现Mock接口调用。
- 实现主流序列化器(jdk,json,kryo,hessian)。可扩展设计:使用工厂模式+单例模式简化创建和获取序列化器对象的操作。并通过扫描资源路径+反射自实现 了 SPI机制(工厂使用静态代码块,在工厂首次(加载/主动使用)时,就会调用 Spiloader 的load 方法加载序列化器接口Serializer的所有实现类,之后就可以通过调用 getlnstance 方法获取指定的实现类实例了),用户也可通过编写配置的方式扩展和指定自己的序列化器。
- 基于 Etcd 云原生中间件实现了高可用的分布式注册中心(结构类似于redis主从集群),采用层级结构的存储结构。Etcd的Java客户端 Jetcd 中的 KvClient 用来存储服务和节点信息,leaseClient管理租约机制,用于为键值对分配生存时间。框架支持通过 SPI机制扩展注册中心。服务提供者启动时进行服务注册(key键名的层级结构规则是 /rpc/服务名:版本号/服务节点地址,value为服务元信息),服务消费者从注册中心获取服务提供者地址,即根据(/rpc/服务名称:版本号)前缀查询,从 Etcd 查询到某个服务的所有节点(服务元信息列表)。
- 注册中心优化: (1)心跳检测和续期机制:服务提供者本地维护一个已注册节点集台,并定期发送(10s)请求到 Etcd 续签自己的注册信息,重写 TTL(30s,重新注册该service即可)。(2)服务节点下线机制:主动下线 -- 服务提供者利用 JVM 的 ShutdownHook 机制(JVM关闭前调用自己的destroy方法),主动从注册中心移除掉已注册的节点(service)。被动下线 -- 服务提供者宕机异常退出,利用 Etcd 的 key 过期机制自动移除。(3)消费端的服务缓存:消费端远程调用之前都会进行服务发现(同时利用 watchClient 对获取到的服务节点 key 进行监听),第一次会查询注册中心并将服务节点信息缓存到本地,之后就不用再去请求注册中心,提高性能。当监听的某个key发生修改或删除时(比如节点下线),则消费端会清理该服务的缓存。
- 自定义协议:(1)具体实现:考虑到HTTP协议头信息较多,基于 Vert.x TCP 服务器 + 类 Dubbo 的紧凑型协议结构(消息头自定义,消息体是RpcRequest /RpcResponse)+ 编解码器(自定义协议消息结构<-->Buffer,编码时候,消息头信息直接添加到Buffer,消息体通过序列化器后添加到Buffer) 自实现了 RPC 协议,提升网络传输性能。(2)半包粘包问题解决(接收端):基于 Vert.x 内置的 RecordParser 解决半包粘包问题,具体思路为由于消息体的长度是不固定的,所以要通过调整 RecordParser 的固定长度(变长)来解决,先完整读取定长的请求头信息,再根据请求头长度信息更改 RecordParser 的固定长度,保证完整获取到请求体。代码使用装饰者模式封装了 TcpBuferHandleWrapper 类,实现并增强Handler接口,之后一行代码即可对原有的请求处理器进行增强,提高代码的可维护性。
- 负载均衡器: 为提高服务提供者集群处理能力,实现了一致性 Hash、轮询、随机等不同算法的负载均衡器,利用指定的负载均衡算法对服务发现后的可用 serviceMetaInfoList 服务元信息列表进行选择。支持通过SPI机制支持开发者自行扩展。
- 重试机制: 为提高服务消费端调用的可靠性和健壮性,基于 Guava Retrying 实现了包括 fixedWait(固定时间间隔),exponentialWait(指数退避) 等多种重试策略,并通过 SPI 机制支持开发者自行扩展。
- 容错机制: 重试次数达到上限之后就会触发容错机制,为进一步提高服务消费端调用的可靠性和健壮性,设计实现了 Fail0ver(故障转移:切换另外一个可用服务节点进行调用)、FailBack(服务降级处理,返回Mock对象)、FailSafe(静默处理,即直接忽略不做任何处理)、Failfast 等多种重试策略(快速失败,立刻报错),并通过 SPI 机制支持开发者自行扩展。
这是一个基于Java的手写简易RPC框架项目,用于分布式系统中不同服务间通信。项目主要包含四个核心模块:
common
:定义通用类和接口,如 User 类和 UserService 接口。consumer
:服务消费者,通过 ServiceProxyFactory 创建代理对象发起远程调用。provider
:服务提供者,将服务本地注册到 LocalRegistry,启动 HTTP 服务器监听端口并处理请求。lzz-rpc-easy
:框架核心模块,包含序列化器、代理、本地注册中心和 HTTP 服务器等功能。
主要内容:
- 使用高性能的NIO框架Vert.x来作为RPC框架的Web服务器
- 实现本地服务注册器,使用线程安全的 ConcurrentHashMap 存储本地服务注册信息,可以根据服务名称获取到对应实现类,并通过反射完成方法调用。
- 实现序列化器,使得Java对象能够网络传输。RPC请求对象主要包括服务接口名,方法名,方法参数类型以及方法实际参数。
- 请求处理器:基于 Vert.x的 Handler 接口实现对请求的异步处理,将请求数据反序列化后,从本地服务注册器中找到服务实现类并通过反射机制调用。
- 实现代理工厂,通过工厂模式给服务接口创建代理对象。Consumer通过动态代理即可实现远程服务调用。