由浅入深理解RPC架构设计

简介: 🌴🌴经常听到大家说不同项目之间调用使用HTTP方式,同一个项目内不同服务之间调用使用RPC方式。今天就来学习一下`RPC框架`,RPC框架由哪些部分组成又是如何一步一步设计出来的。

了解RPC框架

既然要设计RPC框架,就需要先知道什么是RPC

RPC(Remote Procedure Call Protocol)全称远程过程调用 ,像调用本地服务(方法)一样调用服务器的服务(方法)。

RPC又是如何进行调用的呢?

很早的时候,国外的工程师设计了一种能够通过A计算机调用B计算机上边应用程序的技术,这种技术不需要开发人员对于网络通讯了解过多,并且调用其他机器上边程序的时候和调用本地的程序一样方便好用。A机器发起请求去调用B机器程序的时候会被挂起,B机器接收到A机器发起的请求参数之后会做一定的参数转换,最后将对应的程序结果返回给A,这个就是最原始的RPC服务调用了。

通常的RPC架构可分为了以下几个核心组件:

  • Client
  • Client Stub
  • Server
  • Server Stub

Client和Server两个名词的概念一般都比较好理解,前一个是客户端(请求发起方),后一个是服务端(服务提供方)。下面来说一下Server Stub和Client Stub是做什么的。

Client Stub: 就是将客户端请求的参数、服务名称、服务地址进行打包,统一发送给server方。

Server Stub: 简单来说就是,服务端接收到Client发送的数据之后进行消息解包,调用本地方法。

具体的调用流程和关系如下图所示:

rpc1.png

RPC框架整体分析和设计

上面我们已经知道了RPC框架的一些基本概念,接下来对我们的RPC框架进行进一步的分析和设计。

RPC框架调用流程

本地客户端以本地调用方式调用服务,首先需要通知到本地的存根(Client Stub),接着本地存根会进行一些数据格式的包装,网络请求的封装等,最终组装成能够进行网络传输的消息体,按照一定的规则将这个消息体通过Socket发送到指定的目标机器上。

服务端的存根(Server Stub)在接收到相关的数据信息之后,需要将其按照事先约定好的规则进行解码,从而识别到消息体内部的信息,然后将对应的请求转发到本地服务对应的函数中进行处理。处理完的数据需要再通过Socket返回给调用方。

调用方存根在接收到服务方数据的时候,需要进行数据解码,最后得到这次请求的最终结果。

调用的流程如下图所示:

rpc2.png

这幅图只是一个最简单的调用流程,接下来我们尝试在这张调用图的基础上 不断地进行功能扩展,从而最终设计出一个比较完善的RPC框架。

代理层设计

RPC最大的特点就是像调用本地服务(方法)一样调用服务器的服务(方法),实现这一点就需要我们在远程调用的时候,将其中内部的细节进行封装屏蔽,让调用者感知不到远程调用的逻辑。

看了上面的描述会不会联想到代理模式? 由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这个时候,访问对象(Client)不适合或者不能直接引用目标对象(Service)代理对象作为访问对象和目标对象之间的中介

代理模式的主要优点有:

  • 代理模式能将代理对象与真实被调用的目标对象分离;
  • 代理模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用;
  • 代理模式一定程度上降低了系统的耦合度,增加了程序的可扩展性。

所以面对客户端的请求,我们可以增加一个代理层,统一将内部的细节都屏蔽起来,让调用者使用起来无感知。这个时候我们可以用下图表示这个请求调用的流程:

rpc3.png

路由层的设计

当服务提供者有多个的时候,我们就会面临以下问题:当目标服务众多的时候,客户端需要如何确定最终请求的服务提供者是谁呢?

这里就需要引入一个叫做路由的角色,负责遴选出符合条件的服务提供者,此时客户端的调用整体流程大致如下:

rpc4.png

客户端的请求会经过一个叫做路由层的部分,通过路由层内部的规则去选择对应的Server服务。

协议层的设计

客户端在使用RPC框架进行远程调用的时候,还需要对数据信息进行统一的包装和组织,最后才能将其发送到目标机器并且被目标机器接收解析,因此对于数据的各种序列化、反序列化,协议的组装我们统一可以封装在协议层中进行实现,此时客户端的调用整体流程如下图所示:

rpc5.png

router层会负责计算好最终需要调用的服务提供者具体信息,然后将对应的地址信息、请求参数传输给到protocol层,最终由protocol层对数据封装为对应的协议体,然后进行序列化处理,最终通过网络发送给到目标机器。

可插拔式组件设计

从客户端本地请求,到protocol层发送数据,整个链路中可能还需要考虑后续的一些二次扩展设计。例如某些自定义条件的过滤,服务分组等等,所以在设计的时候可以考虑在代理层(proxy)和路由层(router)之间加入一些链路模块。这类设计有点类似于责任链模式,整体的设计结构大致如下:

rpc6.png

可插拔式的组件主要是为了以后方便进行二次扩展。

注册中心层的设计

当服务提供者呈现集群的时候,客户端需要去动态获取服务提供者的诸多信息,那么在这个过程中就需要引入一个叫做注册中心的角色。

服务提供者将自己的地址、接口等详细信息都上报到注册中心模块,并且当服务上线、下线都会通知到注册中心。然后服务调用方只需要订阅注册中心即可。

所以对于注册中心层我们也可以统一抽取一个层面出来,现在我们再来调整下整体的设计结构图:

rpc7.png

市面上有很多注册中心技术,常见的组件有ZooKeeperNacosRedis等等。

容错层的设计

在进行远程调用的过程中,难免会出现一些异常的情况。市面上常见的RPC框架在处理调用异常的时候通常都会提供一些容错方面的处理手段,常见手段如下:

  • 超时重试:当调用某个provider失败的时候,会重试其他provider,可以设置重试次数;
  • 快速失败:当调用某个provider失败的时候,不会重试其他provider,快速返回异常结果;
  • 无限重试:请求失败后会自动会自动记录在失败队列中,并由一个定时线程重试;
  • 异常回调:出现异常后,回调指定方法;
  • 无视失败:出现异常后,不做任何处理。
  • ……

面对这种异常的场景,我们可以尝试将这些处理手段统一抽象出来,交给容错层去处理,所以此时我们需要再对这款RPC框架进行修改:

rpc8.png

服务提供者的线程池设计

当请求发送到了服务提供者的时候,服务提供方需要对其进行相应的解码,然后在本地进行核心处理。我们如果想提升服务器的并发访问,这部分的工作需要交给专门的线程去计算处理。此时我们再对RPC框架的调用图进行修改,大致如下:

rpc9.png

好了到这里,RPC框架已经设计的差不多了,这个就是我们最终设计的RPC框架。

总结

最后我们再做一下总结,在上面一步一步设计完RPC的框架之后,我们的RPC框架的整体结构基本分层为:

  • 代理层:负责对底层调用细节的封装;
  • 链路层:负责执行一些自定义的过滤链路,可以供后期二次扩展;
  • 路由层:负责在集群目标服务中的调用筛选策略;
  • 协议层:负责请求数据的转码封装等作用;
  • 注册中心:关注服务的上下线,以及一些权重,配置动态调整等功能;
  • 容错层:当服务调用出现失败之后需要有容错层的兜底辅助;

另外再附一张业界知名RPC框架Dubbo中各个层依赖关系图作对比:(来自Dubbo官方文档)

来自Dubbo官方文档

🚀🚀🚀

目录
相关文章
|
1月前
|
消息中间件 缓存 API
|
3月前
|
消息中间件 Dubbo Java
Simple RPC - 01 框架原理及总体架构初探
Simple RPC - 01 框架原理及总体架构初探
51 0
|
4月前
|
存储 网络协议 Dubbo
Rpc编程系列文章第一篇:RPC概述和架构演变
Rpc编程系列文章第一篇:RPC概述和架构演变
|
7月前
|
负载均衡 Dubbo Java
RPC框架-dubbo:架构及源码分析-初篇
在自学或面试dubbo时,相关的问题有很多,例如dubbo 的基本工作原理,这是使用过dubbo后应该知道的。包括dubbo的分层架构、长短链接选择、二进制协议支持;之后是使用方式(服务的注册、发现、调用方式),基础配置(超时时间、线程数),这些是最基本的。 在这些问题之后,就可以继续深入底层:关于连接方式,使用长连接还是短连接?为什么? dubbo的二进制协议支持哪些,之间有什么区别/优缺点等等,也可以考察在使用过程中遇到过哪些问题,是如何解决的。这些都需要深入理解,并且有真实、长时间使用经验。
134 0
|
9月前
|
消息中间件 微服务
微服务通信:RPC、消息队列和事件驱动架构的比较
在微服务架构中,微服务之间的通信是至关重要的。为了实现松耦合、高效可靠的通信,开发人员可以选择不同的通信方式,包括RPC(远程过程调用)、消息队列和事件驱动架构。本文将对这三种常见的微服务通信方式进行比较,探讨它们的特点、适用场景和优缺点,帮助开发人员选择合适的通信方式。
226 0
|
11月前
|
数据采集 网络协议 算法
RPC框架整体架构
RPC就是把拦截到的方法参数,转成可以在网络中传输的二进制,并保证在服务提供方能正确地还原出语义,最终实现像调用本地一样地调用远程的目的。
200 0
|
存储 缓存 网络协议
RPC微服务架构:RPC个人浅析(绝对干货)
RPC微服务架构:RPC个人浅析(绝对干货)
364 0
RPC微服务架构:RPC个人浅析(绝对干货)
|
消息中间件 Dubbo NoSQL
微服务架构的常用 RPC 协议 | 学习笔记
快速学习微服务架构的常用 RPC 协议 。
367 0
微服务架构的常用 RPC 协议 | 学习笔记
|
缓存 编解码 监控
看大牛是如何一次性把RPC远程过程调用,Dubbo架构进阶给讲清的
Dubbo架构进阶 Dubbo架构主要包含四个角色:消费者、提供者、注册中心和监控系统。
255 0
看大牛是如何一次性把RPC远程过程调用,Dubbo架构进阶给讲清的
|
存储 缓存 负载均衡
RPC架构设计方法论(完结)
通过一种宏观的视角设计一种灵活的可扩展的RPC架构 分块介绍服务发现、健康监测、路由策略、负载均衡、异常重试的解决方案 如何优雅的启动和关闭RPC服务,以及如何通过熔断限流及业务分组来增强架构的鲁棒能力
RPC架构设计方法论(完结)