RPC与RPC框架

RPC即 Remote Procedure Call ,远程过程调用,一种通信概念,编程模型概念

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

为什么要远程调用

无法在一个进程内,甚至一个计算机内通过本地调用的方式完成的需求,比如不同的系统间的通讯,甚至不同的组织间的通讯。由于计算能力需要横向扩展,需要在多台机器组成的集群上部署应用。又可能需要调用其它服务器服务,或者本地服务器无法完成数据计算,需要调用集群等,算力要扩展,分布式在发展,计算机要通信,RPC诞生。

更多的,很多服务都可以抽出来以责任链模式进行执行:

一个请求应答网络交互通常包含两条链,一条链(Upstream)是从传输层,经过一系列步骤,如身份认证,解密,日志,流控,最后到达业务层,一条链(DownStream)是业务层返回后,又经过一系列步骤,如加密等,又回到传输层。 现代业务需要RPC。

分布式服务中,可以用RPC,但是不是也可以通过Restful API进行调用呢,思想很接近,只不过Restful API基于http/https,报文传输效率不高,同时需要显示发起报文,如何向调用本地方法一样调用远程方法?用RPC

RPC专为远程过程调用而生,基于底层如TCP,自定义报文传输,屏蔽底层细节,核心就是序列化/反序列化+网络通信,这就是很多RPC框架要解决的问题和解决的思路,比如阿里的Dubbo。RPC 是构建分布式应用的理论基础

RPC要解决的两个主要问题:

1. 解决分布式系统中,服务之间的调用问题。

2. 远程调用时,要能够像本地调用一样方便,让调用者感知不到远程调用的逻辑。

RPC过程

首先,要通过在客户端和服务器之间建立TCP连接(也可以使用其它协议如UDP等,只要能完成数据传输就好),远程过程调用的所有交换的数据都在这个连接里传输。RPC协议自定义报文。

第二,解决寻址的问题,也就是说,A服务器上的应用怎么告诉底层的RPC框架,如何连接到B服务器(如主机或IP地址)以及特定的端口,方法的名称名称是什么,这样才能完成调用,即维护一个Map,使用Call-ID与函数指针映射完成调用映射。

第三,数据序列化,方法的参数需要通过底层的网络协议如TCP传递到B服务器,由于网络协议是基于二进制的,内存中的参数的值要序列化成二进制的形式,也就是序列化(Serialize),通过寻址和传输将序列化的二进制发送给B服务器。

第四,服务器数据反序列化,B服务器收到请求后,需要对参数进行反序列化(序列化的逆操作),恢复为内存中的表达方式,然后找到对应的方法(寻址的一部分)进行本地调用,然后得到返回值。

第五,返回值还要发送回服务器A上的应用,也要经过序列化的方式发送,服务器A接到后,再反序列化,恢复为内存中的表达方式,交给A服务器上的应用

img

RPC框架好处

http接口是在接口不多、系统与系统交互较少的情况下,解决信息孤岛初期常使用的一种通信手段;

优点就是简单、直接、开发方便。

如果是一个大型的网站,内部子系统较多、接口非常多的情况下,RPC框架的好处就显示出来了:

RPC框架一般都有注册中心,有丰富的监控管理;发布、下线接口、动态扩展等,对调用方来说是无感知、统一化的操作。

论复杂度,dubbo/hessian用起来超级简单:

调用简单,真正提供了类似于调用本地方法一样调用接口的功能 。

参数返回值简单明了 参数和返回值都是直接定义在jar包里的,不需要二次解析。

轻量,没有多余的信息。

便于管理,基于dubbo的注册中心。

RPC能解耦服务

RPC:远程过程调用。RPC的核心并不在于使用什么协议。RPC的目的是让你在本地调用远程的方法,而对你来说这个调用是透明的,你并不知道这个调用的方法是部署哪里。

通过RPC能解耦服务,这才是使用RPC的真正目的。RPC的原理主要用到了动态代理模式。

RPC框架要解决的问题

RPC原理简单:数据序列化/反序列化+网络通信(如基于TCP的Socket,用Netty),高可用的RPC需要考虑很多

在分布式中,既然是分布式了,那么一个服务可能有多个实例,你在调用时,要如何获取这些实例的地址呢?

这时候就需要一个服务注册中心,比如在Dubbo里头,就可以使用Zookeeper作为注册中心,在调用时,从Zookeeper获取服务的实例列表,再从中选择一个进行调用。

那么选哪个调用好呢?这时候就需要负载均衡了,于是你又得考虑如何实现负载均衡,比如Dubbo就提供了好几种负载均衡策略。

这还没完,总不能每次调用时都去注册中心查询实例列表吧,这样效率多低呀,于是又有了缓存,有了缓存,就要考虑缓存的更新问题,blablabla……

你以为就这样结束了,没呢,还有这些:

  • 客户端总不能每次调用完都干等着服务端返回数据吧,于是就要支持异步调用;
  • 服务端的接口修改了,老的接口还有人在用,怎么办?总不能让他们都改了吧?这就需要版本控制了;
  • 服务端总不能每次接到请求都马上启动一个线程去处理吧?于是就需要线程池;
  • 服务端关闭时,还没处理完的请求怎么办?是直接结束呢,还是等全部请求处理完再关闭呢?
  • ……

如此种种,都是一个优秀的RPC框架需要考虑的问题。

RPC简单实现与问题: https://zhuanlan.zhihu.com/p/36528189

参考:

知乎搜索:RPC

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