本着开源精神,本项目README已经同步了英文版本。另外,项目的源代码的注释大部分也修改成了英文。java
如访问速度不佳,可放在 Gitee 地址:https://gitee.com/SnailClimb/... 。若是要提交 issue 或者 pr 的话,请在 Github 提交:https://github.com/Snailclimb... 。git
相关项目:程序员
虽然说 RPC 的原理实际不难,可是,本身在实现的过程当中本身也遇到了不少问题。guide-rpc-framework 目前只实现了 RPC 框架最基本的功能,一些可优化点都在下面提到了,有兴趣的小伙伴能够自行完善。github
经过这个简易的轮子,你能够学到 RPC 的底层原理和原理以及各类 Java 编码实践的运用。面试
你甚至能够把 guide-rpc-framework 当作你的毕设/项目经验的选择,这是很是不错!对比其余求职者的项目经验都是各类系统,造轮子确定是更加能赢得面试官的青睐。算法
若是你要将 guide-rpc-framework 当作你的毕设/项目经验的话,我但愿你必定要搞懂,而不是直接复制粘贴个人思想。你能够 fork 个人项目,而后进行优化。若是你以为的优化是有价值的话,你能够提交 PR 给我,我会尽快处理。docker
guide-rpc-framework 是一款基于 Netty+Kyro+Zookeeper 实现的 RPC 框架。代码注释详细,结构清晰,而且集成了 Check Style 规范代码结构,很是适合阅读和学习。apache
因为 Guide哥自身精力和能力有限,若是你们以为有须要改进和完善的地方的话,欢迎 fork 本项目,而后 clone 到本地,在本地修改后提交 PR 给我,我会在第一时间 Review 你的代码。json
咱们先从一个基本的 RPC 框架设计思路提及!安全
注意 :咱们这里说的 RPC 框架指的是:可让客户端直接调用服务端方法就像调用本地方法同样简单的框架,好比我前面介绍的 Dubbo、Motan、gRPC 这些。 若是须要和 HTTP 协议打交道,解析和封装 HTTP 请求和响应。这类框架并不能算是“RPC 框架”,好比 Feign。
一个最简单的 RPC 框架使用示意图以下图所示,这也是 guide-rpc-framework 目前的架构 :
服务提供端 Server 向注册中心注册服务,服务消费者 Client 经过注册中心拿到服务相关信息,而后再经过网络请求服务提供端 Server。
做为 RPC 框架领域的佼佼者Dubbo的架构以下图所示,和咱们上面画的大致也是差很少的。
通常状况下, RPC 框架不只要提供服务发现功能,还要提供负载均衡、容错等功能,这样的 RPC 框架才算真正合格的。
简单说一下设计一个最基本的 RPC 框架的思路:
为了按部就班,最初的是时候,我是基于传统的 BIO 的方式 Socket 进行网络传输,而后利用 JDK 自带的序列化机制 来实现这个 RPC 框架的。后面,我对原始版本进行了优化,已完成的优化点和能够完成的优化点我都列在了下面 👇。
为何要把可优化点列出来? 主要是想给哪些但愿优化这个 RPC 框架的小伙伴一点思路。欢迎你们 fork 本仓库,而后本身进行优化。
CompletableFuture
包装接受客户端返回结果(以前的实现是经过 AttributeMap
绑定到 Channel 上实现的) 详见:使用 CompletableFuture 优化接受服务提供端返回结果客户端与服务端通讯协议(数据包结构)从新设计
,能够将原有的
RpcRequest
和
RpcReuqest
对象做为消息体,而后增长以下字段(能够参考:《Netty 入门实战小册》和 Dubbo 框架对这块的设计):
fork 项目到本身的仓库,而后克隆项目到本身的本地:git clone git@github.com:username/guide-rpc-framework.git
,使用 IDEA 打开,等待项目初始化完成。
这一步主要是为了在 commit 代码以前,跑 Check Style,保证代码格式没问题,若是有问题的话就不能提交。
如下演示的是 Mac/Linux 对应的操做,Window 用户须要手动将config/git-hooks
目录下的pre-commit
文件拷贝到 项目下的.git/hooks/
目录。
执行下面这些命令:
➜ guide-rpc-framework git:(master) ✗ chmod +x ./init.sh ➜ guide-rpc-framework git:(master) ✗ ./init.sh
init.sh
这个脚本的主要做用是将 git commit 钩子拷贝到项目下的 .git/hooks/
目录,这样你每次 commit 的时候就会执行了。
IntelliJ IDEA-> Preferences->Plugins->搜索下载 CheckStyle 插件,而后按照以下方式进行配置。
配置完成以后,按照以下方式使用这个插件!
这里使用 Docker 来下载安装。
下载:
docker pull zookeeper:3.5.8
运行:
docker run -d --name zookeeper -p 2181:2181 zookeeper:3.5.8
实现接口:
@Slf4j @RpcService(group = "test1", version = "version1") public class HelloServiceImpl implements HelloService { static { System.out.println("HelloServiceImpl被建立"); } @Override public String hello(Hello hello) { log.info("HelloServiceImpl收到: {}.", hello.getMessage()); String result = "Hello description is " + hello.getDescription(); log.info("HelloServiceImpl返回: {}.", result); return result; } } @Slf4j public class HelloServiceImpl2 implements HelloService { static { System.out.println("HelloServiceImpl2被建立"); } @Override public String hello(Hello hello) { log.info("HelloServiceImpl2收到: {}.", hello.getMessage()); String result = "Hello description is " + hello.getDescription(); log.info("HelloServiceImpl2返回: {}.", result); return result; } }
发布服务(使用 Netty 进行传输):
/** * Server: Automatic registration service via @RpcService annotation * * @author shuang.kou * @createTime 2020年05月10日 07:25:00 */ @RpcScan(basePackage = {"github.javaguide.serviceimpl"}) public class NettyServerMain { public static void main(String[] args) { // Register service via annotation new AnnotationConfigApplicationContext(NettyServerMain.class); NettyServer nettyServer = new NettyServer(); // Register service manually HelloService helloService2 = new HelloServiceImpl2(); RpcServiceProperties rpcServiceProperties = RpcServiceProperties.builder() .group("test2").version("version2").build(); nettyServer.registerService(helloService2, rpcServiceProperties); nettyServer.start(); } }
ClientTransport rpcClient = new NettyClientTransport(); RpcServiceProperties rpcServiceProperties = RpcServiceProperties.builder() .group("test1").version("version1").build(); RpcClientProxy rpcClientProxy = new RpcClientProxy(rpcClient, rpcServiceProperties); HelloService helloService = rpcClientProxy.getProxy(HelloService.class); String hello = helloService.hello(new Hello("111", "222"));
写这个 RPC 框架主要是为了经过造轮子的方式来学习,检验本身对于本身所掌握的知识的运用。
实现一个简单的 RPC 框架实际是比较容易的,不过,相比于手写 AOP 和 IoC 仍是要难一点点,前提是你搞懂了 RPC 的基本原理。
我以前从理论层面在个人知识星球分享过如何实现一个 RPC。不过理论层面的东西只是支撑,你看懂了理论可能只能糊弄住面试官。咱程序员这一行仍是最须要动手能力,即便你是架构师级别的人物。当你动手去实践某个东西,将理论付诸实践的时候,你就会发现有不少坑等着你。
你们在实际项目上仍是要尽可能少造轮子,有优秀的框架以后尽可能就去用,Dubbo 在各个方面作的都比较好和完善。
Java :
CompletableFuture
的使用Netty :
ByteBuf
介绍Zookeeper :