在上一篇博客中,介绍了RPC的主要概念和实现原理,然后基于TCP协议实现了一个非常简单的RPC小案例(点此回顾)。
现在,自我挑战一下,动手写一个RPC框架。
高能预警:本文涉及到的知识点如下
先看下效果
1、配置文件:开启服务注册、ZK地址和连接超时时间、暴露服务端口。
2、服务提供者:用RpcService注解说明该bean提供远程调用服务。
3、服务消费者:RpcReference注解为此属性注入远程调用服务的代理对象。
4、注册中心:服务提供者启动后,在ZK成功创建了相关节点。
5、调用服务:成功发起了一次远程过程调用。
嘀,开车啦!
嗤,源码下载地址:https://download.csdn.net/download/qq_31142553/10913525
敲黑板讲重点!!!
跟Dubbo一样,分为服务提供者、服务消费者、注册中心三个主要角色。后面将逐一进行讲解。
镇楼图:
我们将项目分为两个模块,一个核心模块,一个测试模块。大概代码结构如下
主要maven依赖
org.projectlombok
lombok
io.netty
netty-all
org.apache.zookeeper
zookeeper
3.4.12
因为基于Java Bean的配置比较灵活,所以我们建立一个全局配置类,在这里配置需要交给Spring IOC容器管理的对象。但是,如果系统不打算使用RPC服务,那就没必要加载这个配置类了。因此,我们自定义一个注解,如果在Spring Boot启动类上使用了此注解,那么此全局配置类才生效。
概述
服务提供者系统启动时,如果启用了服务注册功能,就将提供服务的bean信息注册到ZooKeeper,并在内存维护一个interfaceName-bean的映射关系集合,最后在指定端口开启一个监听远程调用请求的服务。
详解
是否启用服务注册功能,可以从配置属性读取。采用条件注解的方式,如果启用了,就注册一个专门用于维护与ZooKeeper的连接会话的实例到IOC容器,在构造函数里面初始化它的ZK实例,并判断是否需要创建ZK的服务根节点。然后,还要注册一个RPC服务到IOC容器,这个服务在Spring容器加载完成之后,获取所有带了自定义的、表示提供远程服务的注解的bean,先将它们存到本地内存维护的一个Map集合里面,以接口全类名为key,bean实例为value,这样,远程过程调用的请求过来之后,就从这个map里面根据接口名找到对应的bean来处理了。然后,还要将这些bean实例信息放到ZK上面,以提供服务消费方去查询获取。至于存什么信息呢?首先是需要这些bean的接口全类名,然后是本机启动的监听请求服务的IP和端口。所以,在ZK服务根节点下,创建一个以接口全类名为名称的永久节点,然后创建一个临时序列子节点,以本机IP和监听端口、当前时间戳(处理一台服务器的一个接口有多个实现类的问题)命名。最后,还要启动一个Netty服务端,绑定本机的IP和端口,端口可以写到配置里面、与前文说的保持一致,添加业务处理的Handler,业务处理主要是根据请求的接口名、方法名、参数列表找到本地内存维护的map里面的服务实例,通过反射调用并返回执行结果。
概述
服务启动时,从注册中心订阅(先查,后续变化自动触发更新)自己需要的服务到本地列表。方法调用时,利用代理先去本地列表查询到服务提供所在IP和端口,然后发起Netty请求,将响应作为远程调用的执行结果返回。
详解
首先,服务消费者系统启动时,先注册一个与ZooKeeper的连接会话的实例到IOC容器。然后,查询所有bean中带了自定义的、表示需要远程服务的注解的属性,根据它们的类型名称到ZK上面查询同名节点,存在的话获取它的所有孩子节点名称,然后保存到一个自己定义的、类似Map
由于代码量有点大,我也不知道怎么贴。就将这些类是做什么用的简单说明一下,比较关键的部分附上截图。
推荐感兴趣的小伙伴直接去下载源码:https://download.csdn.net/download/qq_31142553/10913525
EnableRpcConfiguration:自定义注解,用于Spring Boot启动类上面。有此注解时,配置类RpcConfiguration才生效,系统才使用RPC功能。
RpcReference:自定义注解,用于Spring Bean的属性上,表明此字段需要注入远程调用的代理对象。
RpcService:自定义注解,用于Spring Bean的类上面,表明该实例提供远程调用服务。需要设置interfaces属性,指明提供哪些接口的服务。
NodeChildrenChangedWatcher:子节点变化观察者,用于服务消费者监听ZooKeeper指定节点的变化从而更新服务信息列表。
RpcClientHandler:用于服务消费者向服务提供者发送请求并接收响应。
RpcInjectHandler:客户端核心类,从ZooKeeper获取需要的服务信息,为带RpcReference注解的属性设置远程调用的代理对象。
RpcDecoder:Netty解码器,将字节数组转为Java对象。
RpcEncoder:Netty编码器,将Java对象转为字节数组。
RpcRequest:RPC请求封装类,有接口名称、方法名称、参数列表(类型和值)。
RpcResponse:RPC结果封装类,有响应结果、异常。
Consts:常量,有zk服务根节点 、本机IP。
RpcConfiguration:RPC配置类,配置所有注入IOC容器的bean。
RpcServer:将提供RPC服务的bean存到本地服务列表,并注册到ZooKeeper
RpcServerHandler:处理服务消费者的请求,反射调用本地方法,并将执行结果返回。
ServerListener:开启Netty服务端监听。
HashMultimap:类似Google Guava的同名类,提供Map
IpUtils:获取本机IP地址。
RpcException:RPC异常类。
SerializationUtils:Java内置的序列化和反序列化功能。
ZkClient:维护服务消费者与ZooKeeper的连接会话。
ZkServer:维护服务提供者与ZooKeeper的连接会话,并创建服务根节点(需要的话)。
源码下载地址:https://download.csdn.net/download/qq_31142553/10913525