Skip to content

Latest commit

 

History

History

RPC

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

Remote Procedure Call 远程过程调用

rpc vs ajax

相同点: 两台计算机之间的网络通信 双方约定数据格式

不同点: RPC不一定使用DNS作为寻址服务(一般在内网内相互请求) 应用层协议一般不适用HTTP(二进制协议,更小的数据包体积,更快的编解码速率) ajax -> http协议(文本协议) 基于TCP或UDP协议

寻址过程: ajax通过DNS解析拿到IP,再请求 rpc通过ID拿到IP,在请求

TCP通信方式:

  1. 单工通信 demo
  2. 半双工通信(同一时间内,只有一端能向另一端发送)
  3. 全双工通信(同一时间内,两端能相互收发消息)

nodejs Buffer 编解码二进制数据包

protocol buffer 二进制协议编码库

因为在 TCP 通道里传输的数据只能是二进制形式的,所以我们必须将数据结构或对象转换成二进制串传递给对方,这个过程就叫「序列化」。而相反,我们收到对方的二进制串后把它转换成数据结构或对象的过程叫「反序列化」。而序列化和反序列化的规则就叫「协议」。

把 RPC 的协议分成两大类,一类是通讯层协议,另一类是应用层协议。通讯层协议一般是和业务无关的,它的职责是将业务数据打包后,安全、完整的传输给接受方,HSF、Dubbo、gRPC 这些都是属于通讯层协议。而应用层协议是约定业务数据和二进制串的转换规则,常见的应用层协议有 Hessian,Protobuf,JSON。这两种协议的关注点是不太一样的,对于一个 RPC 框架来说,通讯层协议一旦确定就很少变化,这要求它具备足够好的通用性和扩展性;而应用层协议理论上可以由业务自由选择,它更多的是关注编码的效率和跨语言等特性。RPC 框架的核心是通讯层协议的设计,换句话说你理解了通讯层协议各个字段的含义,基本上也理解了 RPC 原理。

协议设计就像把一个数据包按顺序切分成若干个单位长度的「小格子」,然后约定每个「小格子」里存储什么样的信息,一个「小格子」就是一个 Byte,它是协议设计的最小单位,1 Byte 是 8 Bit,可以描述 0 ~ 2^8 个字节数,具体使用多少个字节要看实际存储的信息。我们在收到一个数据包的时候首先确定它是请求还是响应,所以我们需要用一个 Byte 来标记包的类型,比如:0 表示请求,1 表示响应。知道包类型后,我们还需要将请求和它对应的响应关联起来,通常的做法是在请求前生成一个「唯一」的 ID,放到 Header 里传递给服务端,服务端在返回的响应头里也要包含同样的 ID,这个 ID 我们选择用一个 Int32 类型(4 Bytes)自增的数字表示。要能实现包的准确切割,我们需要明确包的长度,Header 长度通常是固定的,而 Payload 长度是变化的,所以要在 Header 留 4 个 Bytes(Int32) 记录 Payload 部分的长度。确定包长度后,我们就可以切分出一个个独立的包。Payload 部分编码规则由应用层协决定,不同的场景采用的协议可能是不一样的,那么接收端如何知道用什么协议去解码 Payload 部分呢?所以,在 Header 里面还需要一个 Byte 标记应用层协议的类型,我们称之为 Codec。现在来看看我们设计的协议长什么样:

0      1      2      3      4      5      6      7      8      9     10
+------+------+------+------+------+------+------+------+------+------+
| type |          requestId        | codec|         bodyLength        |
+------+---------------------------+------+---------------------------+
|                  ...          payload                               |
|                                                     ...             |
+---------------------------------------------------------------------+

多路复用RPC通道

Node.js 的 Net模块用于创建基于流的 TCP 或 IPC 的服务器(net.createServer())与客户端(net.createConnection())。

Node.js 的 Net模块是基于TCP协议的socket网路编程模块。

半双工通信需要带上序号,才能转换为全双工通信。如果服务端响应不带上序号,一旦发生延迟等情况,客户端无法确认响应是哪个请求的,请求包和返回包错乱。需要添加包序号确认顺序。

tcp底层会自动把同时发的包拼接起来,拼成打包 -> 粘包,需要分包操作 demo

则需要自动拆解包 demo