RPC全称Remote Procedure Call,即远程过程调用,对于调用者无感知这是一个远程调用功能 。目前流行的开源RPC 框架有阿里的Dubbo、google 的 gRPC、Twitter 的Finagle 等 。本次RPC框架的设计主要参考的是阿里的Dubbo,这里Netty 基本上是作为架构的技术底层而存在的,主要完成高性能的网络通信,从而实现高效的远程调用 。
Dubbo的架构与Spring其实在之前的文章中《谈谈京东的服务框架》,探讨过Dubbo的组成和架构 。
文章插图
文章插图
另外使用Dubbo最方便的地方在于它可以和Spring非常方便的集成,Dubbo对于配置的优化也是随着Spring一脉相承的,从最早的XML形式到后来的注解方式以及自动装配,都是在不断地简化开发过程来提高开发效率 。
Dubbo在Spring框架中的工作流程:
1、Spring的IOC容器启动
2、把服务注册到注册中心(zookeeper软件)中
3、消费者启动时会把它需要用到的服务从注册中心拉取下来
4、提供者的地址发生改变时,注册中心会马上通知消费者
5、根据注册中心中的服务地址直接就可以调用提供者了,如果调用了提供者,就会把提供者的地址主动缓存起来
6、监控消费者调用提供者的次数
RPC实现的关键1、序列化与反序列化
在远程过程调用时,客户端跟服务端是不同的进程,甚至有时候客户端用JAVA,服务端用C++ 。这时候就需要客户端把参数先转成一个字节流,传给服务端后,再把字节流转成自己能读取的格式,这个过程叫序列化和反序列化,同理,从服务端返回的值也需要序列化反序列化的过程 。在序列化的时候,我们选择Netty自身的对象序列化器 。
文章插图
2、数据网络传输
解决了序列化的问题,那么剩下的就是如何把数据参数传到生产者,网络传输层需要把序列化后的参数字节流传给服务端,然后再把序列化后的调用结果传回客户端,虽然大部分RPC框架都采用了TCP作为传输协议,其实UDP也可以作为传输协议的,基于TCP和UDP我们可以自定义任意规则的协议,加之我们要使用NIO通信方式作为高性能网络服务的前提,于是Netty似乎更符合我们Java程序员的口味,Netty真香!
3、告诉注册中心我要调谁
现在调用参数的序列化和网络传输都已经具备,但是还有个问题,那就是消费者要调用谁的问题,一个函数或者方法,我们可以理解为一个服务,这些服务注册在注册中心上面,只有当消费者告诉注册中心要调用谁,才可以进行远程调用 。所以不但要把将要调用的服务的参数传过去,也要把要调用的服务信息传过去 。
简易RPC框架的架构
文章插图
Dubbo 核心模块主要有四个:Registry 注册中心、Provider 服务提供者、Consumer 服务消费者、Monitor监控,为了方便直接砍掉了监控模块,同时把服务提供者模块与注册中心模块写在一起,通过实现自己的简易IOC容器,完成对服务提供者的实例化 。
关于使用Netty进行Socket编程的部分可以参考Netty的官网 或者我之前的博客《Netty编码实战与Channel生命周期》,在这里Netty的编码技巧和方式不作为本文的重点 。
RPC框架编码实现首先需要引入的依赖如下(Netty + Lombok):
<dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.6.Final</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.16.8</version></dependency>
1、Registry与Provider目录结构如下:
───src└─main├─java│└─edu│└─xpu│└─rpc│├─api││IRpcCalc.java││IRpcHello.java│││├─core││InvokerMessage.java│││├─provider││RpcCalcProvider.java││RpcHelloProvider.java│││└─registry│MyRegistryHandler.java│RpcRegistry.java│└─resources───pom.xml
IRpcCalc.java与IRpcHello.java是两个Service接口 。IRpcCalc.java内容如下,完成模拟业务加、减、乘、除运算public interface IRpcCalc {// 加int add(int a, int b);// 减int sub(int a, int b);// 乘int mul(int a, int b);// 除int div(int a, int b);}
IRpcHello.java,测试服务是否可用:public interface IRpcHello {String hello(String name);}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 银杏叶片治疗脑供血不足吗,银杏叶片可以长期吃
- 养肝祛斑茶,桑叶茶的功效
- 六种肾病可以治愈,六种搭配效果佳
- 鲜迷迭香可不可以生吃,迷迭香怎么吃
- 哪些药物可以降转氨酶
- a十c群流脑疫苗有什么作用?
- 凝血八因子作用
- 玉蝴蝶泡水天可以喝多少,桑葚干泡水天需几粒黑桑椹干泡水喝多少
- 发型|我真的没整容,就是换了换发型,你要不信我带你去找Tony
- 苹果|APP卸载一年多仍扣费2500多元!苹果客服:出于同情 可以退300多