高并发架构系列:RPC通信机制你了解吗

前言

在分布式系统中,因为每个服务的边界都很小,很有可能调用别的服务提供的方法。这就出现了服务A调用服务B中方法的需求,即远程过程调用。

要想让服务A调用服务B中的方法,最先想到的就是通过HTTP请求实现。是的,这是很常见的,例如服务B暴露Restful接口,然后让服务A调用它的接口。基于Restful的调用方式因为可读性好(服务B暴露出的是Restful接口,可读性当然好)而且HTTP请求可以通过各种防火墙,因此非常不错。

然而,基于Restful的远程过程调用有着明显的缺点,主要是效率低、封装调用复杂。当存在大量的服务间调用时,这些缺点变得更为突出。

服务A调用服务B的过程是应用间的内部过程,牺牲可读性提升效率、易用性是可取的。基于这种思路,基于TCP模式RPC产生了。通常,RPC要求在调用方中放置被调用的方法的接口。调用方只要调用了这些接口,就相当于调用了被调用方的实际方法,十分易用。于是,调用方可以像调用内部接口一样调用远程的方法,而不用封装参数名和参数值等操作。

RPC简介

RCP即远程过程调用,它是一个计算机通信协议,允许调用者像调用本地服务一样调用远程服务,下面这张图是典型的RPC调用图:

RPC是怎么实现远程过程调用的呢?

服务端将对外接口以jar包的形式发布,客户端引用服务端发布的jar包。n多个接口调用过程中,每个接口如何找到对应的实现类呢,这时候JDK动态代理就派上用场了,客户端发送接口调用请求,动态代理接收到调用后,将进行一系列操作实现远程接口的调用。整过调用过程将进行一下几个步骤:

客户端:

①自定义请求协议。protocol是client与server交互的语法。Http定义了http请求协议规则,Dubbo定义了Dubbo协议请求规则,我们也可以自定义请求协议。客户端按照协议组装数据,并发送至服务端;服务端按照协议解析客户端请求数据,执行客户端请求接口方法,把结果按照协议组装发送至客户段端;最后客户端按照协议解析服务端的返回结果。

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

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

é«å¹¶åæ¶æç³»åï¼RPCæ¡æ¶çå®ç°åçï¼è°ç¨å¨è¿ç¨ï¼åRPCæ¶æç»ä»¶

可靠的寻址方式(主要是提供服务的发现)是RPC的实现基石,比如可以采用redis或者zookeeper来注册服务等等。

④建立通信。首先要解决通讯的问题:即A机器想要调用B机器,首先得建立起通信连接。

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

服务端:

反序列化

当B机器接收到A机器的应用发来的请求之后,又需要对接收到的参数等信息进行反序列化操作(序列化的逆操作),即将二进制信息恢复为内存中的表达方式,然后再找到对应的方法(寻址的一部分)进行本地调用。

②本地接口调用,请求处理。

③结果返回。服务端对返回结果进行序列化,再经过网络传输将二进制数据发送回A机器,而当A机器接收到这些返回值之后,则再次进行反序列化操作,恢复为内存中的表达方式,最后再交给A机器上的应用进行相关处理(一般是业务逻辑处理操作)。

RPC调用过程图解:

é«å¹¶åæ¶æç³»åï¼RPCæ¡æ¶çå®ç°åçï¼è°ç¨å¨è¿ç¨ï¼åRPCæ¶æç»ä»¶

 

1、服务消费者(client客户端)通过本地调用的方式调用服务

2、客户端存根(client stub)接收到调用请求后负责将方法、入参等信息序列化(组装)成能够进行网络传输的消息体

3、客户端存根(client stub)找到远程的服务地址,并且将消息通过网络发送给服务端

4、服务端存根(server stub)收到消息后进行解码(反序列化操作)

5、服务端存根(server stub)根据解码结果调用本地的服务进行相关处理

6、本地服务执行具体业务逻辑并将处理结果返回给服务端存根(server stub)

7、服务端存根(server stub)将返回结果重新打包成消息(序列化)并通过网络发送至消费方

8、客户端存根(client stub)接收到消息,并进行解码(反序列化)

9、服务消费方得到最终结果

Protocol

 protocol是client与server交互的语法。Http定义了http请求协议规则,Dubbo定义了Dubbo协议请求规则,我们也可以自定义请求协议。客户端按照协议组装数据,并发送至服务端;服务端按照协议解析客户端请求数据,执行客户端请求接口方法,把结果按照协议组装发送至客户段端;最后客户端按照协议解析服务端的返回结果

Serial

客户端和服务端之间的通讯是基于TCP协议的,TCP传输的数据全都是byte流。如此,一个会话的处理流程为:首先,dsf客户端把请求数据(调用接口方法、参数)转化(序列化)为byte数组,发送到服务端;接着,服务端接收到byte数组,把byte数组反向转化(反序列化)为请求数据(调用接口方法、参数),根据请求数据执行具体的接口实现类的方法并得到执行结果,完了把结果转化(序列化)为byte数组,发送到客户端;最后,客户端接收到服务端发送的byte数组,把byte数组反向转化(反序列化)为执行结果。如下图所示:

dubbo架构

dubbo是一个高性能高扩展性的rpc服务调用框架,它的rpc调用过程也遵循上面的流程,dubbo架构图如下:

包含四个核心组件:

1)服务消费者,远程服务的调用端;

2)服务提供者,提供远程服务;

3)服务注册中心,提供的服务发现、容灾、降级等服务治理能力;

4)服务监控,监控和统计服务的健康程度。

理论上只需要有消费者和提供者就能实现远程服务调用了,但在实际的生成环境中注册中心的服务治理能力和监控组件的监控能力对一个健康的系统是不可或缺的。

 

文章参考:

https://baijiahao.baidu.com/s?id=1640952736297475769&wfr=spider&for=pc

https://www.toutiao.com/a6797580498257314307/

https://www.toutiao.com/a6631154767844344327/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章