问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

RPC笔记:概念、调用流程与RESTful API的区别

创作时间:
作者:
@小白创作中心

RPC笔记:概念、调用流程与RESTful API的区别

引用
CSDN
1.
https://blog.csdn.net/wohu1104/article/details/120004719

1. 基本概念

RPC(Remote Procedure Call)是一种远程过程调用技术,它允许一个节点请求另一个节点提供的服务。当两个物理分离的子系统需要建立逻辑上的关联时,RPC是常见的技术手段之一。除了RPC之外,常见的多系统数据交互方案还有分布式消息队列、HTTP请求调用、数据库和分布式缓存等。

  • 本地过程调用:如果要将本地的对象进行相关操作,可以定义一个方法,然后将相关对象传入,然后对其对象进行更新,然后由函数返回更新后的函数对象。
  • 远程过程调用:在上述过程中,如果其定义的函数是在另外一个服务器端,并且执行的函数体也是在另外一台远程服务器上,那么这个过程就称之为远程过程调用。

2. 调用过程

其调用过程如下所示:

  1. 首先客户端需要告诉服务器端,需要调用的函数,然后这里的函数和进程ID存在一个映射,客户端远程调用的时候,需要查询一下函数,找到对应的ID,然后执行对应函数的代码。
  2. 客户端需要把本地参数传递给远程函数,在本地调用的过程中,会通过把参数转换为字节码,然后再传递给服务端,最后服务端再转换为自身可以读取的格式,这是一个序列化和反序列的过程。
  3. 转换完成数据以后,在进行传输的过程一般是使用HTTP,Socket协议进行传输。

除去RPC调用以外,还有RESTful API进行调用。RESTful API调用其示例图如下图所示:

在上图中,一个服务A如果访问另外一个服务器下的B,这个过程采用的就是RESTful API进行数据的传输。并且两个过程的数据会进行序列化和反序列化炒作。

两种方式进行对比而言,

  • RPC通信代价比较低,因为RPC是直接基于TCP进行调用的,并且传输的数据都是基于TCP进行的,所以效率更高,更优。但是由于是基于TCP的所以实现起来更为的复杂,更为的难以维护。
  • 而RESTful API由于是直接基于HTTP的所以实现更为简单,维护更为容易。
  • RPC快,效率高,但是不够通用,就好比地方方言,HTTP通用是普通话,但是效率不够高,传输的字节内容冗余多。
  • REST相对更规范,更标准,更通用,简单易用,维护性和扩展性都比较好。
  • RPC+Protobuf采用的是TCP做传输协议,REST直接使用HTTP做应用层协议,这种区别导致REST在调用性能上会比RPC+Protobuf低。

Go语言中常用的API风格是RPC和REST,常用的媒体类型是JSON、XML和Protobuf。在Go API开发中常用的组合是gRPC+Protobuf和REST+JSON。

其实业界普遍采用的做法是,内部系统之间调用用RPC,对外用REST,因为内部系统之间可能调用很频繁,需要RPC的高性能支撑。对外用REST更易理解,更通用些。当然以现有的服务器性能,如果两个系统间调用不是特别频繁,对性能要求不是非常高,REST的性能完全可以满足。

HTTP调用其实也是一种特殊的RPC。HTTP1.0协议时,HTTP调用还只能是短链接调用,一个请求来回之后连接就会关闭。HTTP1.1在HTTP1.0协议的基础上进行了改进,引入了KeepAlive特性可以保持HTTP连接长时间不断开,以便在同一个连接之上进行多次连续的请求,进一步拉近了HTTP和RPC之间的距离。

当HTTP协议进化到2.0之后,Google开源了一个建立在HTTP2.0协议之上的通信框架直接取名为gRPC,也就是Google RPC。

3. 解决问题

总之,RPC解决掉了在分布式系统之中,服务之间调用的问题。让服务在远程调用的时候,能够像本地调用一样非常方便,并且让调用者感知不到远程调用的具体逻辑。RPC只是对底层通信和交互协议的一个封装,便于上层使用。

4. 调用流程

一般来说调用过程如下所示:

  1. 调用者,以本地调用方式发起调用。
  2. Client stub客户端收到调用以后,将会把被调用的方法名,参数进行打包编码成为特定的格式,包装成为能够被网络传输的消息体。
  3. Client stub将消息体通过网络发送给服务端。
  4. Server stub将会收到通过网络接收到的消息后按照相应的格式进行拆分,获取方法名称和及其调用传入的参数。
  5. 被调用者Server本地调用执行后将会把结果返回给Server stub。
  6. Server stub将会将返回值打包编码成为消息,然后通过网络发送给客户端。
  7. Client stub收到消息以后,将会进行拆分,然后返回给CLient。
  8. Client最终获得本地RPC调用结果。

RPC传输控制

对于消息数据的传输,主要有HTTP传输和TCP传输,一般来说RPC使用TCP进行传输,因为TCP其要优于HTTP传输。

传输过程如下图所示:

传输的时候一般通过Socket接口进行传输,也有使用HTTP作为底层的传输的结果,但是使用HTTP传输的比较少。

其过程如下:

  1. Server发起创建套接字请求。
  2. 创建套接字后绑定相关端口
  3. 监听链接
  4. 进入接收连接状态中。
  5. Client端创建套接字
  6. Client端和Server端刚刚建立完成的Socket进行连接的建立。
  7. Server端进行读取,Client进行数据写。
  8. Client端进行数据读取,
  9. 双方交换完数据以后,关闭连接。

Server端代码示例:

import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(("localhost", 8080))
sock.listen(1)  # 监听客户端连接
while True:
    conn, addr = sock.accept()  # 接收一个客户端连接
    print(conn.recv(1024))
    conn.sendall(b"world")  # 将响应发送到发送缓冲 send buffer
    conn.close()

输出结果

b'hello'

Client端代码示例:

import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(("localhost", 8080))
sock.sendall(b"hello")  # 将消息输出到发送缓冲 send buffer
print(sock.recv(1024))
sock.close()

输出结果

b'world'

问题:客户端疯狂发送请求,但是服务器不读不处理,会发生什么?

  • 如果接收和发送队列没有设置大小,服务器处理能力弱,tcp会动态调整直至耗尽整个内存;
  • 设置了大小,socket缓冲区满,那么socket会出现阻塞,不接受发送端的消息;
  • 如果发送的请求size大于发送和接收队列之和,那么会一直阻塞下去;

5. 远程调用时序图

  1. 本地RPCTest类,将会调用ServiceProducer在服务端注册并启动Server。
  2. Server将会调用register和start进行初始化应用。
  3. RPCTest将会通过Client调用本地方法。
  4. Client将会调用远程服务器方法ServiceProducer并传入本地阐述,将消息发送给Server端。
  5. Server端放过反射,压入ServerTask。
  6. ServerTask将会远程执行方法。
  7. 最后调用栈,调用完成以后,将结果返回给Server。
  8. Server通过网络传输信息到Client。
  9. Client把结果最终返回给RPCTest。
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号