RPC:Remote Procedure Call(远程服务调用)

RPC是做什么的

通过RPC框架机器A某个进程可以通过网络调用机器B上的进程方法,就像在本地上调用一样。
RPC可以基于HTTP或者TCP协议通信,TCP协议相对性能较高。

调用图示(引用zhanglijun童鞋的图)

图片描述:

  1. client发出调用方法(服务)的请求
  2. client stub作为中转站,进行请求接口、方法、参数以及服务地址、请求Id的封装,包装成RequestMessage对象、序列化——编码,最后传输到网络上去
  3. 服务端(service)经过网络接受到RequestMessage
  4. 首先server stub进行字节流的反序列化、解析requestMessage——解码,最后将请求转发给server
  5. server调用method(...),返回结果给server stub
  6. server stub将result、返回状态码、请求id等进行包装成ResponseMessage、序列化——编码、传输
  7. client stub得到字节流,进行反序列化、解析ResponseMessage——解码,将结果返给client
  8. client最终得到结果

RPC框架就是将2-7这几个步骤封装起来,帮忙处理网络IO、编解码、序列化、服务寻址等工作,这些工作对于调用方和服务方都是透明的。由此,我们也可以得出结论,我们就需要使用代码实现2-7步骤所需要处理的工作。下面列举实现一个轻量级RPC框架所需要解决的几个问题。

RPC框架的实现需要解决的几个问题

如果想实现一个轻量级rpc框架需要解决什么问题呢:

请求封装问题

机器A想要调用机器B上面的方法method(),那么A机器就需要详细描述自己的需求——要调用那个ip上那个端口的进程、调用哪个service,这些都需要描述清楚。

详细如下:

  • 接口名称,一个接口提供一种服务,比如HelloworldService
  • 方法名称,定位一个接口内的某个方法
  • 参数——类型与值,client调用就需要client指定入参,服务端是肯定不知道这些的
  • 超时时间
  • requestId,每一个client发出请求时都需要绑定一个唯一指定requestId,这是因为在并发请求的时候一个服务方可能服务多个client的请求,有了这个requestId,client stub才能将返回结果发放给特定的请求线程而不会混淆。

返回消息对象封装问题

  • 返回值
  • 状态code,表示这次请求成功与否
  • requestid

序列化的问题

网络IO需要传输请求消息对象以及响应消息对象,这样才能达到双方通信的目的。但是网络是以字节(byte)准确的说是比特传输信息的,因此需要一种技术将对象转换成字节(序列化),以及再将字节转换成对象(反序列化)。java自身是有序列化工具的,借助ObjectOutputStream等类就可以序列化对象。但是他的性能、拓展性都不是很好,因此一般借助于第三方的序列化工具

目前,互联网公司主流使用protobuf、thrift、jackson、hessian等

网络通信问题

消息序列化之后就是网络通信了,使用java nio是可以实现一个通信框架的,但这属于高难度动作——专家模式。就码农way而言,使用netty通信框架,省事省力,经过测试完善的框架也不容易出错

服务发布的问题

一般情况,如果客户端依赖的服务挂掉或者切换地址等,那么客户端可能就无法工作或者需要改变配置。为了能够达到自动切换服务、寻址等问题,就需要一个服务注册和发现功能的框架。市面上流行的是zookeeper,他可以将上线的服务注册进去,提供给客户端调用。zookeeper会不断对服务进行心跳检测,一旦服务挂掉,就会在注册中心把他消掉。客户端可以在注册中心切换到其他可用的服务

zookeeper的服务注册格式:/{service}/{version}/{ip:port}

关于RPC框架的初体验

这里并不是商用的RPC框架,没有服务治理、插件支持等功能,使用的是@黄勇写的轻量级分布式 RPC 框架,目的在于理解rpc框架核心代码的功能模块结构、相关技术选型以及如何运行等几个问题

关于框架的几点理解

  • rpc-sample-api模块,定义了服务接口,这个代码无论客户端和服务端都需要用到的
  • rpc-sample-server模块,对rpc-sample-api的接口进行了实现,启动RpcBootstrap类,就会将rpc-server模块写的RPCServer和注入容器中。这个模块相当于前面LBS大大图片里的server端,真正提供服务的实现的模块
  • rpc-server模块,相当于server stub,他负责将扫描到的被@RpcService注解的类注册到zookeeper,对请求、返回值消息进行序列化、编解码,处理请求等
  • rpc-client模块,就相当于client stub,他负责将client的请求进行编码,发送出去,到zookeeper注册中心去发现可用服务,进行调用
  • rpc-register-zookeeper模块,该模块的ZookeeperServiceDiscovery类为rpc-client模块提供服务发现功能。而zookeeperServiceRegistry类为rpc-server模块提供了服务注册的功能。其实就是实例化一个ZkClient对zookeeper服务进行访问,然后对zookeeper进行注册服务和发现服务
  • rpc-common模块,定义了一些工具类和消息对象。消息对象用于封装请求和返回值消息,工具类主要用于序列化、编解码等功能

最后,由于本人之前并没有对netty和protobuf等工具有详细了解,代码细节无法详述,这里只是简单地归纳出该框架的几点模块关系以及作用

运行步骤

这里主要是本人运行该框架的几个步骤,其实非常简单

  • 下载源码到IDEA,地址https://gitee.com/huangyong/rpc.git
  • 安装、启动zookeeper服务,不了解的童鞋可以参考 zookeeper安装和使用 windows环境
  • 启动rpc-server,就是rpc-sample-server下的RpcBootstrap类即可,这边服务端就算启用了

  • 接下来运行rpc-sample-client下面的几个类,可以看到客户端代码其实是通过RpcProxy.create(...)获取实例,并得到了返回值

小结

本文总结了RPC服务是做什么的以及RPC框架相关的几个概念,接下来描述了如果我们自己写RPC框架需要解决的几个问题。并且使用@黄勇童鞋的开源demo,进行rpc使用的初体验,勉强对rpc框架有了基本的认识。如果想深入使用、了解的童鞋可以尝试使用阿里的hsf、谷歌的gRpc构建自己的微服务应用或者分布式计算等

参考

你应该知道的RPC原理

轻量级分布式 RPC 框架

RPC框架基础概念理解以及使用初体验的更多相关文章

  1. RPC 框架 Dubbo 从理解到使用(二)

    本篇文章为系列文章,未读第一集的同学请猛戳这里:RPC 框架 Dubbo 从理解到使用(一) 本篇文章讲解 Dubbo 支持的注册中心.Dubbo 负载均衡策略和 Dubbo 控制台的安装. 注册中心 ...

  2. RPC 框架 Dubbo 从理解到使用(一)

    技术架构演变 单一应用架构 通俗地讲,"单体应用(monolith application)"就是将应用程序的所有功能都打包成一个独立的单元.当网站流量很小时,只需一个应用,将所有 ...

  3. WCF分布式开发步步为赢(1):WCF分布式框架基础概念

    众所周知,系统间的低耦合一直是大型企业应用系统集成追寻的目标,SOA面向服务架构的出现为我们的如何利用现有企业系统资源进行企业ERP系统设计和实现提供了重要的参考原则.SOA如此炙手可热,各大厂商都推 ...

  4. (一)SpringBoot基础篇- 介绍及HelloWorld初体验

    1.SpringBoot介绍: 根据官方SpringBoot文档描述,BUILD ANYTHING WITH SPRING BOOT (用SPRING BOOT构建任何东西,很牛X呀!),下面是官方文 ...

  5. (一)SpringBoot2.0基础篇- 介绍及HelloWorld初体验

    1.SpringBoot介绍: 根据官方SpringBoot文档描述,BUILD ANYTHING WITH SPRING BOOT (用SPRING BOOT构建任何东西,很牛X呀!),下面是官方文 ...

  6. Elasticsearch基础概念理解

    熟悉ES中的几个关键概念: 节点(Node):一个elasticsearch运行的实例,其实就是一个java进程.一般情况下,一台机器运行在一台机器上. 集群(Cluster): 好几个有相同集群名称 ...

  7. Struts2框架基础概念总结

    一.struts2框架 Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的 ...

  8. JAVA类与对象(一)----基础概念理解

    面向对象基本概念 面向对象是一种新兴的程序设计方法,或者说是一种新的程序设计规范,其基本思想是使用对象.类.继承.封装.消息等基本概念来进行程序设计.它是从现实世界客观存在的事物(即对象)出发来构造软 ...

  9. 基础概念——理解IP地址和域名

    从程序员角度,可以把因特网看做是世界范围内的主机集合: 1)主机集合被映射为一组32位的IP地址. 2)这个IP地址被映射为一组称为因特网域名的标识符. 3)因特网主机上的进程能够通过连接和任何其他因 ...

随机推荐

  1. attr()与setAttribute()的区别

    先看红色标注的: 这里传过来的this是个元素节点,因此currentTr也得用获取节点的方式parentNode去获取,而不能写parent(),这是第一个需要注意的地方. 第二个问题,就是怎么给c ...

  2. 了解委托(Delegate)

    委托是一种全新面向对象语言特性,运行在.Net平台 基于委托,开发事件驱动程序变得非常简单 使用委托可以大大简化多线程变成的难度 理解委托 int a:   //定义变量 a=100://给变量赋值 ...

  3. nopCommerce 3.9 中文语言包

    点击下载:nopCommerce 3.9 中文语言包 nopCommerce39语言包.xml 下载后解压通过后台导入即可使用.如何导入?点击这里

  4. CSS超链接的常见设置

    一般对超连接常见的设置,就是设置文字大小,下划线,颜色等等. 先讲解一下,超链接的四种状态 /* 未被访问的链接 */ a:link {color:#FF0000;} /* 已被访问的链接 */ a: ...

  5. JavaScript 对象继承 OOP (三)

      对象继承 A 对象通过继承 B 对象,就能直接拥有 B 对象的所有属性和方法.这对于代码的复用是非常有用的. JavaScript 语言的继承不通过 class (es6 中的class 不过是 ...

  6. ionic1跨域问题

    在使用ionic是遇到跨域问题 我自己尝试简单的单间一个能返回数据的后台服务器,ionic的www目录我使用一个ionic的livereload 来当做一个简易的web服务器,在使用ionic ser ...

  7. java,eclipse中如何添加httpclient.jar

    1.Download 'Binary' package of the latest official release from the project download page. There sho ...

  8. 02、体验Spark shell下RDD编程

    02.体验Spark shell下RDD编程 1.Spark RDD介绍 RDD是Resilient Distributed Dataset,中文翻译是弹性分布式数据集.该类是Spark是核心类成员之 ...

  9. Js Date类型

    一:格式化方法 var box=new Date(); //标准时间,如果没传参数,得到的时间为当前时间 //alert(Date.parse('4/12/2007')); //11763072000 ...

  10. 《孵化Twitter》:Twitter创始人勾心斗角史,细节披露程度令人吃惊

    本书详细讲述twitter的发展史.感觉基本上是一部创始人从朋友变敌人,勾心斗角的历史.Twitter本身的产品发展反而相对比较简单. 书中披露了许多email.谈话.会议的细节,作者说这些是数百个小 ...