在分布式系统中,RPC(远程过程调用)、和HTTP调用都被广泛使用,下面我详解高并发下,RPC为什么比HTTP调用更快。
协议更轻量,传输开销更小
HTTP是一种通用超文本传输协议,设计初衷是为了支持浏览器与服务器之间的资源访问。
因此它的请求头、响应头以及文本化表达都相对较重。
例如HTTP/1.1请求:
POST /user/get HTTP/1.1
Host: xxx.com
Content-Type: application/json
Content-Length: xxx
{
"userId":10001
}
里面包含:
请求行
Header
Body
服务端收到以后,还需要进行HTTP协议解析。
相比之下,RPC通常采用更轻量的私有协议或二进制协议,去掉了许多对服务调用并不必要的通用字段。
例如:
请求ID
服务名
方法名
参数
序列化数据
然后直接交给RPC框架处理。
RPC则会尽量压缩协议内容,只保留调用方法、参数和返回值等核心信息。
因此,在相同业务请求下,RPC传输的数据量通常更小,网络耗时也更低。
序列化效率更高
这是RPC性能优势中最容易理解的一点。
假设我们调用一个用户服务:
getUser(10001)
如果使用传统HTTP + JSON,可能会传输类似这样的数据:
{
"userId": 10001,
"name": "mikechen",
"age": 30
}
JSON最大的特点是:
可读性很好,但数据冗余比较多。
例如:
"userId"
"name"
"age"
这些字段名称本身也需要进行网络传输。
而很多RPC框架会使用:
Protobuf
Thrift
Hessian
Kryo
等序列化方式。
例如Protobuf会根据预先定义的数据结构进行二进制编码:
message User {
int64 userId = 1;
string name = 2;
int32 age = 3;
}
最终传输的是更加紧凑的二进制数据。
所以整个过程可以理解成:
HTTP + JSON
对象
↓
JSON序列化
↓
文本数据
↓
网络传输
↓
JSON反序列化
↓
对象
RPC:
对象
↓
二进制序列化
↓
更小的数据包
↓
网络传输
↓
二进制反序列化
↓
对象
数据量减少之后,网络传输时间和序列化/反序列化成本都会下降。
连接复用与通信模型更高效
这是RPC性能优化中非常关键的一点。
假设客户端每调用一次服务,都重新建立TCP连接:
Client
↓
TCP三次握手
↓
发送请求
↓
服务器响应
↓
关闭连接
一次请求就建立一次连接。
如果QPS非常高,就会产生大量连接建立和关闭的成本。
例如:
10000 QPS
意味着可能产生非常大量的连接操作。
RPC框架通常会维护连接池:
Client
│
├── Connection 1
├── Connection 2
├── Connection 3
└── Connection 4
↓
RPC Server
建立连接之后,可以持续发送大量请求:
Connection 1
├── Request 1
├── Request 2
├── Request 3
├── Request 4
└── Request 5
这样就避免了大量重复的,握手和挥手过程,从而在高并发环境下表现得更快、更稳。
以上