RPC原理

目录

1、为什么要有RPC?

2、什么是RPC?

3、服务提供者挂了,注册中心如何知道服务不可用了呢?

4、注册中心挂了呢?

5、rpc原理架构图

6、rpc原理

7、现有框架对比

8、如何设计一个rpc框架

9、Dubbo为什么要自定义协议,而不用现成的Http协议?

10、既然有了 HTTP,还要有 RPC 协议? 

1、为什么要有RPC?

1、单一应用架构

当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。此时,用于简化增删改查工作量的数据访问框架(ORM) 是关键。

2、垂直应用架构

当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互不相干的几个应用,以提升效率。此时,用于加速前端页面开发的 Web框架(MVC) 是关键。

3、分布式服务架构

当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。

此时,用于提高业务复用及整合的分布式服务框架(RPC),提供统一的服务是关键。

例如:各个团队的服务提供方就不要各自实现一套序列化、反序列化、网络框架、连接池、收发线程、超时处理、状态机等“业务之外”的重复技术劳动,造成整体的低效。

2、什么是RPC?

RPC(Remote Procedure Call Protocol)远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。简言之,RPC使得程序能够像访问本地系统资源一样,去访问远端系统资源。比较关键的一些方面包括:通讯协议、序列化、资源(接口)描述、服务框架、性能、语言支持等。

图片描述

  1. 服务集成 RPC 后,服务(这里的服务就是图中的 Provider,服务提供者)启动后会通过 Register(注册)模块,把服务的唯一 ID 和 IP 地址,端口信息等注册到 RPC 框架注册中心(图中的 Registry 部分)。
  2. 当调用者(Consumer)想要调用服务的时候,通过 Provider 注册时的的服务唯一 ID 去注册中心查找在线可供调用的服务,返回一个 IP 列表(3.notify 部分)。
  3. 第三步 Consumer 根据一定的策略,比如随机 or 轮训从 Registry 返回的可用 IP 列表真正调用服务(4.invoke)。
  4. 最后是统计功能,RPC 框架都提供监控功能,监控服务健康状况,控制服务线上扩展和上下线(5.count)

3、服务提供者挂了,注册中心如何知道服务不可用了呢?

主动下线:重启之前先主动通知注册中心,流量进来先让别的机器服务,等我重启成功后在放流量进来,或者是在管理后台手动直接摘掉机器。

心跳检测:比如每隔 30s 发送一个心跳,如果三次心跳结果都没有返回值,就认为该服务已下线,会主动推送消息更新 Consumer 的服务列表。

4、注册中心挂了呢?

调用者本地会缓存注册中心获取的服务列表。省略和注册中心的交互,Consumer 和 Provider 采用直连方式,这些策略都是可配置的。

5、rpc原理架构图

1、客户端(Client):服务调用方(服务消费者)

2、客户端存根(Client Stub):存放服务端地址信息,将客户端的请求参数数据信息打包成网络消息,再通过网络传输发送给服务端

3、服务端存根(Server Stub):接收客户端发送过来的请求消息并进行解包,然后再调用本地服务进行处理

4、服务端(Server):服务的真正提供者

RPC原理_第1张图片

 

6、rpc原理

两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的函数/方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据。

1、建立通信

即A机器想要调用B机器,首先得建立起通信连接。主要是通过在客户端和服务器之间建立TCP连接,远程过程调用的所有交换的数据都在这个连接里传输。连接可以是按需连接,调用结束后就断掉,也可以是长连接,多个远程过程调用共享同一个连接。

2、服务寻址

A服务器上的应用怎么告诉底层的RPC框架,如何连接到B服务器(如:IP地址以及特定的端口,方法的名称是什么)。通常情况下我们需要提供B机器(主机名或IP地址)以及特定的端口,然后指定调用的方法或者函数的名称以及入参出参等信息,这样才能完成服务的一个调用。可以采用redis或zookeeper来注册服务。

3、序列化和反序列化

序列化:当A机器上的应用发起一个RPC调用时,调用方法和其入参等信息需要通过底层的网络协议如TCP传输到B机器,由于网络协议是基于二进制的,所有我们传输的参数数据都需要先进行序列化(Serialize)成二进制的形式才能在网络中进行传输。然后通过寻址操作和网络传输将序列化或者编组之后的二进制数据发送给B机器。

反序列化:接收到的参数等信息进行反序列化操作(序列化的逆操作),即将二进制信息恢复为内存中的表达方式,然后再找到对应的方法(寻址的一部分)进行本地调用(一般是通过生成代理Proxy去调用, 通常会有JDK动态代理、CGLIB动态代理、Javassist生成字节码技术等),之后得到调用的返回值。

4、服务调用

B机器进行本地调用(通过代理Proxy和反射调用)之后得到了返回值,此时还需要再把返回值发送回A机器,同样也需要经过序列化操作,然后再经过网络传输将二进制数据发送回A机器,而当A机器接收到这些返回值之后,则再次进行反序列化操作,恢复为内存中的表达方式,最后再交给A机器上的应用进行相关处理(一般是业务逻辑处理操作)。

RPC原理_第2张图片

RPC原理_第3张图片

 

7、现有框架对比

RPC原理_第4张图片

8、如何设计一个rpc框架

RPC原理_第5张图片

调用方执行方法后,实际上执行的是代理类的方法,代理类帮我们进行序列化和编解码操作。如何生成代理类呢?Facebook的Thrift和Google的grpc都是定义一个schema文件,然后执行程序,帮你生成客户端代理类,以及接口。调用方直接用生成的代理类来请求,提供方继承生成的接口即可

优点:能进行多语言通信而且是二进制协议,通讯效率比较高。

在Java中生成代理类的方式有如下几种

  • JDK动态代理(实现InvocationHandler接口)
  • 字节码操作类库(如cglib,Javassist)

9、Dubbo为什么要自定义协议,而不用现成的Http协议?

最主要的原因就是自定义协议可以提高性能

Http协议的请求包比较大,有很多无用的内容。自定义协议可以精简很多内容
Http协议是无状态的,每次都要重新建立连接,响应完毕后将连接关闭

10、既然有了 HTTP,还要有 RPC 协议? 

RPC,因为它定制化程度更高,可以采用体积更小的 Protobuf 或其他序列化协议去保存结构体数据,同时也不需要像 HTTP 那样考虑各种浏览器行为,比如 302 重定向跳转啥的。因此性能也会更好一些,这也是在公司内部微服务中抛弃 HTTP,选择使用 RPC 的最主要原因。

参考:

看了这篇Dubbo RPC面试题,让天下没有难面的面试题! - 知乎 

 

你可能感兴趣的:(RPC,rpc,spring,网络协议)