跳转至

引言

20240618154020

如果想将数据从一台电脑发送到另一台电脑,可以使用 Socket 编程,由于 TCP 是基于字节流传输的协议,无法区分数据边界,会有粘包问题

UDP 是基于数据报的传输协议,无论应用层交给 UDP 多长的报文,UDP 都照样发送,交给 IP 层处理,而 IP 层只管运输不涉及是否粘包,所以 UDP 不会有粘包问题,但是不可靠。

所以需要加一些特殊标志以及消息长度等来区分边界,于是基于 TCP 就衍生出了 RPC 和 HTTP 等各种协议。

RPC 协议的具体实现有很多,至今没有一个统一标准。

起初在 C/S 架构中,客户端只需访问自家公司的服务端即可,所以使用各自的 RPC 协议就可以。

但随着 B/S 浏览器的兴起,需要访问不同公司的服务器,因此需要一个统一的标准协议,不然无法通信,于是诞生了 HTTP(HyperText Transfer Protocol 超文本传输协议)。

也就是说 RPC 通常用于 C/S 架构,HTTP 通常用于 B/S 架构,不过如今很多公司的服务端要同时支持移动端,PC 端以及 Web 端,所以对外提供服务通常使用标准的 HTTP 协议,而 RPC 开始退居幕后,主要用于公司内部集群中各个微服务之间的通信

服务发现

客户端若想与服务端建立连接,需要先知道服务端或资源的位置

在 HTTP 协议中,知道域名后,通过 DNS 服务解析即可获取到 IP,端口默认 80

RPC 协议中会有专门的中间服务保存服务名和 IP 信息等,要想访问某个服务就需要先到这些中间服务获取信息,通常称作服务发现,比如

  • Consul:提供服务注册、服务发现、健康检查等功能。
  • Eureka:Netflix 开源的服务发现和注册工具,广泛用于微服务架构。
  • Zookeeper:Apache 项目,提供分布式协调和服务发现功能。
  • Etcd:CoreOS 开发的分布式键值存储,用于服务发现和配置管理。
  • Redis

服务发现通常用于企业内部或云环境中,动态处理服务实例的注册和查找,适应快速变化的服务环境

长连接

HTTP 1.0 每次请求都需要 TCP 三次握手,请求完后则会断开,即短连接。而 HTTP 1.1 在建立底层 TCP 连接后,会一直保持连接,供之后的请求都复用,即长连接。

请求和返回都可以使用头字段 Connection: keep-alive 来表示长连接,如果服务端返回 Connection: close 则表示不支持长连接。

RPC 协议跟 HTTP 类似,也是建立 TCP 长连接进行数据交互,但不同的地方在于,RPC 协议一般还会再建个连接池,大大的提升了网络请求性能

很多编程语言的网络库也会给 HTTP 加连接池来提高性能,比如 Go

序列化

HTTP 协议通常使用 JSON 来序列化结构体数据

RPC 不需要考虑重定向等浏览器行为,可以使用体积更小的序列化协议,不同的 RPC 可以根据自身特点定制化,比如 gRPC 使用 protobuf

因此 RPC 传输内容性能更好,这就是微服务之间采用 RPC 协议的主要原因

不过 HTTP 2.0 改进提升了性能,比很多 RPC 协议还要好,以至于 gRPC 底层都使用了 HTTP 2.0

RTT

RTT, Round-Trip Time,往返时延,是指一个数据包从发送到确认接收所需的时间,可以理解为两端之间往返一次数据所需的时间。

TCP 握手需要 1.5 RTT

TLS 四次握手需要 2 RTT