什么是RPC?什么是Restful?它们有什么区别?

RPC【什么是RPC?什么是Restful?它们有什么区别?】远程过程调用(Remote Procedure Call,RPC)框架作为架构微服务化的基础组件,能大大降低架构微服务化的成本,提高服务调用方与服务提供方的开发效率,屏蔽跨进程调用函数(服务)的各类复杂细节,其调用原理如图6-13所示 。让服务提供方像实现本地函数一样来实现分布式服务,开发人员不用考虑底层通信协议;让服务调用方像调用本地函数一样调用远端函数,多数RPC框架以面向接口的方式提供远程方法的调用,对开发人员非常友好 。
客户端存根(client stub)用于存放服务器端地址信息,将客户端的请求参数数据信息打包成网络消息,再通过网络传输发送给服务器端 。服务器端存根接收客户端发送过来的请求消息并进行解包,再调用本地服务进行处理 。
RPC的原理与我们平时打电话的过程非常相似 。服务消费者叫作客户端,服务提供者叫作服务器端,两者通常位于网络上两个不同的地址,要完成一次RPC调用,就必须先建立网络连接 。建立连接后,双方必须按照某种约定的协议进行网络通信,这个协议就是通信协议 。双方能够正常通信后,服务器端接收到请求时,需要以某种方式进行处理,处理成功后,把请求结果返回给客户端 。为了减少传输的数据大小,要对数据进行压缩,也就是对数据进行序列化 。为了实现远程服务的调用,RPC框架要做到如下最基本的4件事 。

什么是RPC?什么是Restful?它们有什么区别?

文章插图
 
▲图6-13 RPC框架调用原理
1.客户端如何找到服务器端地址要完成一次服务调用,首先要解决的问题是服务调用方如何得到服务提供方的地址,其中注册中心扮演了关键角色,服务提供方把自己所提供的服务列表以及当前节点地址登记到注册中心,服务调用方就可以查询注册中心以得到服务提供方的地址 。为了实现去中心化设计,多数RPC产品采用本地负载均衡策略,即调用方启动时从注册中心拉取服务地址信息后,在本地缓存,运行过程中真正发起调用时,直接从本地缓存读取服务地址信息,根据一定的负载均衡算法选取某一个地址,发起点对点的直接调用 。这样就避免了中心化的服务总线进行服务路由,运行效率更高,弹性伸缩更方便 。当服务器端地址信息发生变更时(如节点上下线),由注册中心实时推送变更信息到所有的调用方同步更新 。
2.服务器端如何处理请求当使用基于RPC的进程间通信时,客户端向服务器端发起请求,服务器端处理该请求并发回响应 。有些客户端可能处在阻塞状态直到得到响应,而有些客户端可能会有一个响应式的非阻塞架构 。与使用消息机制的完全异步化架构不同,RPC客户端都假定响应会及时到达 。
在远程调用中,客户端和服务器端已经建立了网络连接,服务器端又该如何处理客户端的请求呢?通常来讲,服务器端I/O的方式通常分为3种处理方式:同步阻塞(Blocking I/O,BIO)方式、同步非阻塞(Non-blocking I/O,NIO)方式、异步非阻塞(Asynchronous I/O,AIO)方式 。
(1)同步阻塞方式 。
客户端每发一次请求,服务器端就生成一个线程去处理 。当客户端同时发起很多请求时,服务器端需要创建很多线程去处理每一个请求,如果达到了系统最大的线程数,新的请求就没法处理了 。
(2)同步非阻塞方式 。
NIO本身是基于事件驱动思想来完成的,其主要解决的是BIO的高并发问题:在使用同步I/O的网络应用中,如果要同时处理多个客户端请求或是在客户端同时和多个服务器进行通信,就必须使用多线程来处理 。也就是说,将每一个客户端请求分配给一个线程来单独处理 。这样做虽然可以达到我们的要求,但同时又会带来另一个问题 。由于每创建一个线程,就要为这个线程分配一定的内存空间(也叫工作存储器),而且操作系统本身对线程的总数有一定的限制 。如果客户端的请求过多,服务器端程序可能会因为不堪重负而拒绝客户端的请求,甚至服务器可能因此而瘫痪 。
NIO基于reactor,当socket有流可读或可写入socket时,操作系统会相应地通知应用程序进行处理,应用程序再将流读取到缓冲区或写入操作系统 。也就是说,这时已经不是一个连接就要对应一个处理线程了,而是有效的请求对应一个线程 。当连接没有数据时,是没有工作线程来处理的 。BIO与NIO的一个比较重要的不同之处在于,我们使用BIO时往往会引入多线程,每个连接对应一个单独的线程 。而NIO使用单线程或者只使用少量的多线程,多个连接共用一个线程 。


推荐阅读