当你在构建一个分布式体系时,势必需求考虑的一个问题是:如何完结服务与服务之间的调用?当然,你能够运用 Dubbo 或 Spring Cloud 等分布式服务结构来封装技能完结的复杂性,以此完结这个方针。不过,假如现在没有这些结构,需求你自己来完结长途调用,你会怎么做呢?

许多人会选择完结一套 RPC 结构来调用长途服务。

那么你了解 RPC 架构的根本结构吗?假如你想要自己完结 RPC 结构来完结长途调用,又该构建怎么样的技能体系呢?接下来,我就给你详细介绍一下。

文章首发公众号:码猿技能专栏

RPC 架构的根本结构

想要构建一套完好的 RPC 架构,就需求明确该架构所具有的根本结构,而 RPC 架构的根本结构中又存在许多组件。因而接下来,我就经过 RPC 根本结构演进的进程,来给你一一讲解下。

首先,咱们一般把产生调用关系的两个服务分别称为服务的供给者(Provider)和顾客(Consumer)。所以,简略来说,RPC 便是服务的顾客向供给者建议长途调用并获取成果的进程,这是 RPC 最简略的一种表现形式。

10分钟带你彻底搞懂 RPC 架构

假如想要完结服务供给者和顾客之间的有效交互,那么两者之间就需求树立与网络通讯相关的网络协议以及通讯通道。同时,服务的供给者需求把自己的服务调用进口露出出来,并时刻预备接收来自顾客的恳求。

这儿,咱们把通讯通道和网络协议分别命名为 RpcChannel 和 RpcProtocol,而把服务供给者接收恳求的组件称为 RpcAcceptor,把顾客建议恳求的组件称为 RpcConnector。这样,RPC 架构就演变成了这个样子:

10分钟带你彻底搞懂 RPC 架构

然后,关于服务供给者和顾客而言,为了双方能够正常辨认所发送的恳求和所接收到的呼应成果,需求界说统一的契约。咱们把这种契约称为长途 API(Remote API),以便与本地 API 加以差异。如此一来,根据同一套长途 API 的界说,RPC 架构就具有了根据事务来界说通讯契约的才能。

10分钟带你彻底搞懂 RPC 架构

类似地,为了更好地区分 RPC 架构中的人物,咱们把真正供给事务服务的组件称为 RpcServer,而把建议真实客户端恳求的组件称为 RpcClient。这样,RpcServer 担任完结长途 API,而 RpcClient 担任调用长途 API。

10分钟带你彻底搞懂 RPC 架构

当然,关于长途 API 而言,服务供给者和顾客的处理方法显然是不相同的。供给者需求根据顾客的恳求来调用 RpcServer 的详细完结并回来成果,这部分的工作由 RpcInvoker 来履行,而顾客经过 RpcCaller 组件对恳求进行编码之后,发送给服务方并等候成果。

10分钟带你彻底搞懂 RPC 架构

最终,为了下降开发人员的开发难度,让长途调用的履行进程看上去就像在履行本地办法相同,在干流的 RPC 完结机制中,一般都会在客户端增加署理机制,以此供给长途服务本地化拜访的进口,咱们把这个署理组件称为 RpcProxy。

别的,在服务器端,为了更好地操控事务办法履行进程,一般也会引进具有线程管理、超时操控等机制的 RpcProcessor 组件。

10分钟带你彻底搞懂 RPC 架构

以上便是整个 RPC 架构的演进进程了。从中你能够发现,RPC 架构中的客户端组件和服务器端组件构成了一种对称结构,它们各司其职,但又一起构成一个整体。为了帮你加深了解,这儿我再总结下前面提到的各个组件。

关注公众号:码猿技能专栏,回复关键词:1111 获取阿里内部java功能调优手册

客户端组件与责任包含:

  • RpcClient,担任调用长途 API,这个进程会依赖于 RpcProxy 供给的署理完结
  • RpcProxy,长途 API 的署理完结,供给长途服务本地化拜访的进口
  • RpcCaller,担任编码和发送调用恳求到服务方并等候成果
  • RpcConnector,担任与服务端树立通讯通道并发送恳求到服务端

服务端组件与责任包含:

  • RpcServer,担任完结长途 API
  • RpcInvoker,担任调用服务端的详细完结并回来成果
  • RpcProcessor,担任对恳求进行处理,高效操控调用进程
  • RpcAcceptor,担任接收客户方恳求并回来恳求成果

而客户端和服务器端所共有的组件包含:

  • RpcProtocol,担任网络传输协议的编码和解码
  • RpcChannel,担任树立和维护网络数据传输通道

这样,咱们对一个典型 RPC 架构中的根本结构和组件就有了完好的了解。那么,假如咱们想要完结这个架构,需求构建怎样的技能体系呢?

RPC 架构的技能体系

咱们都知道,架构是一种规划上的思想和办法,了解了它的根本结构和组成部分之后,咱们就能够进一步梳理想要完结 RPC 架构的技能体系,包含网络通讯、序列化、传输协议和长途调用。

网络通讯

咱们先来看网络通讯。网络通讯的触及面很广,关于 RPC 架构而言,一方面咱们会要点关注功能,所以势必要考虑根据 TCP 等特定协议的网络衔接方法和 IO 模型;另一方面,咱们也需求考虑牢靠性,因为这样才能保证长途调用进程的稳定。

好,下面咱们就详细来看看。

首先是功能问题。一般来说,根据 TCP 协议的网络衔接有两种根本方法:长衔接和短衔接。长衔接和短衔接的实质差异是衔接的创立和封闭策略,长衔接能够复用现有衔接,而短衔接则能够更快地释放资源。这两者自身各有利弊,而在 RPC 结构的完结进程中,考虑到功能和服务治理等因素,咱们一般是运用长衔接进行通讯,典型的完结结构便是 Dubbo。

而关于 IO 模型,最简略、最基础的网络 IO 模型便是阻塞式 IO,即 BIO(Blocking IO)。BIO 要求客户端恳求数与服务端线程数一一对应,但是显然,因为线程的创立需求消耗体系资源,在分布式体系中,服务端能够创立的线程数将会成为体系的瓶颈。

因而,在 RPC 架构中,咱们一般都会运用非阻塞 IO,即 NIO(Non-blocking IO)技能来供给功能。根据 NIO 形式下的多路复用机制,创立少量的线程就能对许多恳求进行高效的呼应。

然后是针对牢靠性问题,因为存在网络闪断、超时等与网络状况相关的不稳定性因素,以及事务体系自身的毛病,网络之间的通讯就必须在产生上述问题时能够快速感知并修正。常见的网络通讯保障手法,包含链路有效性检测及断线之后的重连处理等。这些机制都比较常见,也不是咱们讨论的要点,这儿就不做详细展开了。

序列化

而假如咱们想要在网络上传输数据,就需求用到数据序列化技能了。

现在业界老练的序列化东西已经有许多,常见的 XML 和 JSON 便是文本类序列化方法的代表,它们能够让数据以开发人员可读的方法进行传输。还有一种根据二进制完结的方案,包含 Google 的 Protocol Buffer 和 Facebook 的 Thrift。

那么,咱们在选择序列化东西时,应该考虑什么呢?一个关键指标便是功能。

功能指标首要包含空间复杂度、时刻复杂度以及 CPU/ 内存资源占用等。我鄙人表列举了现在干流的一些序列化技能,供你参阅:

10分钟带你彻底搞懂 RPC 架构

能够看到,在时刻维度上,Alibaba 的 fastjson 具有一定优势;而从空间维度上看,相较其他技能,你能够优先选择 Protocol Buffer。

传输协议

咱们知道,凡是触及经过网络来传输数据,就一定要采用某种传输协议。在 ISO/OSI 的 7 层网络模型中,RPC 架构的规划和完结一般会触及传输层及以上各个层次的相关协议,咱们所了解的 TCP 协议就归于传输层,而 HTTP 协议则坐落运用层。

无论是采用 7 层网络模型中的哪一层,在网络恳求进程中,数据都是以音讯的形式进行传递。而音讯的组成是有一定结构的,音讯头和音讯体构成了所传输音讯的主体,其中音讯体表明需求传输的事务数据,而音讯头用于进行传输操控。

10分钟带你彻底搞懂 RPC 架构

能够看到,每个层次都从上层获得数据,加上音讯头信息构成新的音讯体,并将新的音讯传递给下一层次。经过对音讯头和音讯体进行扩展,咱们就能够完结私有化的传输协议。

这也是大部分 RPC 结构内部所采用的完结方法,这样做的首要目的是对公有协议进行精简,然后提高功能。别的,出于扩展性的考虑,具有高度定制化的私有协议也比公共协议愈加简单完结扩展。这方面的典型示例还是 Dubbo 结构,它供给了完全自界说的 Dubbo 协议。

长途调用

明确了网络通讯的根本方法、序列化手法以及所采用的传输协议之后,咱们就能够建议真正的长途调用了。RPC 实质也是一种服务调用,而服务调用存在两种根本方法,即单向(One Way)形式和恳求应答(Request-Response)形式,前者体现为异步操作,后者一般履行同步操作。

首先咱们要知道,同步调用会构成事务线程阻塞,但开发和管理会相对简略。这是为什么呢?咱们先来看一下同步调用的时序图:

10分钟带你彻底搞懂 RPC 架构

从中能够看到,服务线程发送恳求到 IO 线程之后,就一直处于等候阶段,直到 IO 线程完结与网络的读写操作之后,才会被自动唤醒。

而运用异步调用的目的就在于获取高功能。在完结异步调用进程中,咱们一般都会运用到 Java 中所供给的 Future 机制。Future 调用能够进一步细分红两种形式,Future-Get 形式和 Future-Listener 形式。Future-Get 形式参阅下图:

10分钟带你彻底搞懂 RPC 架构

能够看到在这种形式下,服务线程经过自动 get 成果的方法获取 Future 成果,而这个 get 进程是串行的,会构成履行 get 办法的线程构成阻塞。

Future-Listener 形式则不同,在 Future-Listener 形式中需求创立 Listener,当 Future 成果生成时会唤醒注册到该 Future 上的 Listener 对象,然后构成异步回调机制。

除了同步和异步调用之外,还存在并行(Parallel)调用和泛化(Generic)调用等调用办法,虽然也有其特定的运用场景,但关于 RPC 架构而言并不是干流的调用方法,这儿就不详细展开了。

总结

能够说,RPC 是分布式体系中一项基础设施类的技能体系,凡是触及服务与服务之间的交互就需求运用到 RPC 架构。当你在运用一个分布式结构时,能够尝试用今日介绍的 RPC 架构的根本结构和技能体系进行分析,然后加深对这项技能体系的了解。