RPC 核心概念 03序列化与传输协议一次 RPC 调用的数据流主要由两部分构成序列化协议决定数据如何变成字节序列传输协议决定字节序列如何在网络上传输。理解二者的本质才能在不同业务场景做出正确选型。一、序列化协议1.1 为什么需要序列化进程内的对象是有指针、有结构的网络只能传字节。我们必须把对象**编码marshal成字节流对端再解码unmarshal**回对象。1.2 主流序列化协议对比协议编码方式性能体积可读性跨语言典型框架JSON文本慢大好全HTTP APIXML文本慢大好全SOAPProtobuf二进制 TLV快小差强gRPC、tRPCThrift Binary二进制快小差强Apache ThriftMessagePack二进制快小差强Redis、FluentdAvro二进制 Schema快小差强Kafka、HadoopFlatBuffers零拷贝极快中差强游戏、移动端1.3 选型建议场景推荐浏览器/移动端调试JSON内部高性能 RPCProtobuf大规模数据存储Avro实时游戏低延迟FlatBuffers海量日志MessagePack / Protobuf二、Protobuf 序列化原理再深入2.1 TLV 编码field_number wire_type payloadwire_type 共 6 种Wire Type名称用于的类型0Varintint32, int64, bool, enum164-bitfixed64, double2Length-delimitedstring, bytes, embedded message, repeated3Start group废弃4End group废弃532-bitfixed32, float2.2 Varint变长整数小的数字用更少字节0~1271 字节128~163832 字节大数最多 10 字节每个字节最高位作为还有后续字节的标识。150 10010110 00000001 ↑MSB1继续 ↑MSB0结束 解码去掉 MSB → 0010110 0000001 → 翻转 → 0000001 0010110 → 1502.3 ZigZag 编码由于 Varint 对负数高位全 1效率极差sintXX类型先做 ZigZag 转换0 → 0 -1 → 1 1 → 2 -2 → 3 ...把符号位折叠到末位让小绝对值的负数也只占一个字节。2.4 实战手算编码message Person { int32 age 1; }Person{age: 100}的编码[tag(field1,type0)] [varint(100)] 0x08 0x64总共 2 字节。三、传输协议3.1 OSI 模型回顾应用层 HTTP, gRPC, Thrift, tRPC 传输层 TCP, UDP, QUIC 网络层 IPRPC 关注应用层 传输层。3.2 直接基于 TCP很多自研 RPC 框架如早期 Dubbo、自研协议直接基于 TCP自己定义魔数 长度 头部 body格式-------------------------------- | MAGIC | VERSION| TYPE | RESERVED| -------------------------------- | MSG_LENGTH | ----------------------------------- | HEADER | ----------------------------------- | BODY | -----------------------------------优点极致性能缺点缺乏标准基础设施支持如 LB、Ingress 都对 HTTP 友好。3.3 基于 HTTP/1.1最大优势是通用性——所有网络设施都认识 HTTP。但 HTTP/1.1 有头部冗余、队头阻塞等问题不适合高性能 RPC。3.4 基于 HTTP/2gRPC 的选择HTTP/2 的关键特性二进制帧取代文本协议多路复用单 TCP 上并行多个 stream消除队头阻塞HPACK 头压缩极大减少头部体积服务端推送流式传输。这正是 gRPC 选择 HTTP/2 的原因。一次 gRPC 调用 一个 HTTP/2 stream请求/响应都用 trailers 携带 status。3.5 基于 QUICHTTP/3QUIC 基于 UDP解决了 TCP 队头阻塞、连接迁移等问题。gRPC 已实验性支持。3.6 tRPC 的多协议设计tRPC 不绑死任何协议协议是可插拔的默认trpc协议基于 TCPprotobuf可配置 HTTPJSON可与 gRPC 互通也支持自定义协议server:service:-name:trpc.app.server.Helloprotocol:trpc# 切到 grpc / http 改一行四、连接管理4.1 短连接 vs 长连接模式适用短连接调用极少、跨网络层长连接RPC、WebSocket、数据库RPC 默认使用长连接 多路复用。4.2 连接池为目标服务维护一组连接ServiceA → [ conn1, conn2, conn3 ] → ServiceB关键参数max_idle空闲上限max_active活跃上限idle_timeout空闲超时4.3 Keep-Alive定期发送心跳维持长连接、检测半开连接client:keepalive_time:30skeepalive_timeout:10s五、半包与粘包TCP 是面向字节流的没有消息边界。如果应用层不处理就会出现粘包两条消息粘到一起半包一条消息被切成两段。解决方案定长每条消息固定长度适合简单协议分隔符用特殊字节作结束符如 HTTP 用\r\n\r\nTLV/HeaderBody最常用先读固定长度的 headerheader 中带 body 长度再读 body。Protobuf RPC 框架普遍使用第三种。六、流量控制与背压HTTP/2 内置流量控制每个 stream 都有 window接收方处理不过来会让发送方阻塞。tRPC、gRPC 都依赖该机制做反压避免下游被打爆。七、压缩减少带宽消耗但增加 CPU 开销。常见算法算法速度压缩比gzip中中snappy快低zstd较快高lz4极快低gRPC/tRPC 都支持在调用级别启用压缩client.Hello(ctx,req,client.WithCompressType(codec.CompressTypeGzip))八、实战抓包看一次 gRPC 调用# 前置开启 tcpdumpsudotcpdump-ilo0-wgrpc.pcap port9000# 用 wireshark 打开# 设置 HTTP/2 解析Edit Preferences Protocols HTTP2你会看到HTTP/2 帧HEADERS、DATA、TRAILERHEADERS 中的:path /package.Service/MethodDATA 中的 protobuf 字节TRAILER 中的grpc-status: 0。九、序列化性能优化技巧消息池化使用sync.Pool复用 message 对象零拷贝尽量用bytes类型而非string频繁转换批量调用合并多次小调用为一次预分配 slice/map 容量慎用反射protojson 比 json.Marshal 慢优先二进制。十、小结序列化决定数据格式传输协议决定数据怎么走Protobuf 通过 TLVVarintZigZag 实现紧凑高效HTTP/2 是 RPC 的现代标配多路复用解决了队头阻塞解决粘包长度前缀法是工业标准选型时综合考虑性能、可读性、生态。下一篇我们将进入分布式 RPC 的灵魂服务发现与负载均衡。
RPC 核心概念 03:序列化与传输协议
发布时间:2026/5/21 19:30:18
RPC 核心概念 03序列化与传输协议一次 RPC 调用的数据流主要由两部分构成序列化协议决定数据如何变成字节序列传输协议决定字节序列如何在网络上传输。理解二者的本质才能在不同业务场景做出正确选型。一、序列化协议1.1 为什么需要序列化进程内的对象是有指针、有结构的网络只能传字节。我们必须把对象**编码marshal成字节流对端再解码unmarshal**回对象。1.2 主流序列化协议对比协议编码方式性能体积可读性跨语言典型框架JSON文本慢大好全HTTP APIXML文本慢大好全SOAPProtobuf二进制 TLV快小差强gRPC、tRPCThrift Binary二进制快小差强Apache ThriftMessagePack二进制快小差强Redis、FluentdAvro二进制 Schema快小差强Kafka、HadoopFlatBuffers零拷贝极快中差强游戏、移动端1.3 选型建议场景推荐浏览器/移动端调试JSON内部高性能 RPCProtobuf大规模数据存储Avro实时游戏低延迟FlatBuffers海量日志MessagePack / Protobuf二、Protobuf 序列化原理再深入2.1 TLV 编码field_number wire_type payloadwire_type 共 6 种Wire Type名称用于的类型0Varintint32, int64, bool, enum164-bitfixed64, double2Length-delimitedstring, bytes, embedded message, repeated3Start group废弃4End group废弃532-bitfixed32, float2.2 Varint变长整数小的数字用更少字节0~1271 字节128~163832 字节大数最多 10 字节每个字节最高位作为还有后续字节的标识。150 10010110 00000001 ↑MSB1继续 ↑MSB0结束 解码去掉 MSB → 0010110 0000001 → 翻转 → 0000001 0010110 → 1502.3 ZigZag 编码由于 Varint 对负数高位全 1效率极差sintXX类型先做 ZigZag 转换0 → 0 -1 → 1 1 → 2 -2 → 3 ...把符号位折叠到末位让小绝对值的负数也只占一个字节。2.4 实战手算编码message Person { int32 age 1; }Person{age: 100}的编码[tag(field1,type0)] [varint(100)] 0x08 0x64总共 2 字节。三、传输协议3.1 OSI 模型回顾应用层 HTTP, gRPC, Thrift, tRPC 传输层 TCP, UDP, QUIC 网络层 IPRPC 关注应用层 传输层。3.2 直接基于 TCP很多自研 RPC 框架如早期 Dubbo、自研协议直接基于 TCP自己定义魔数 长度 头部 body格式-------------------------------- | MAGIC | VERSION| TYPE | RESERVED| -------------------------------- | MSG_LENGTH | ----------------------------------- | HEADER | ----------------------------------- | BODY | -----------------------------------优点极致性能缺点缺乏标准基础设施支持如 LB、Ingress 都对 HTTP 友好。3.3 基于 HTTP/1.1最大优势是通用性——所有网络设施都认识 HTTP。但 HTTP/1.1 有头部冗余、队头阻塞等问题不适合高性能 RPC。3.4 基于 HTTP/2gRPC 的选择HTTP/2 的关键特性二进制帧取代文本协议多路复用单 TCP 上并行多个 stream消除队头阻塞HPACK 头压缩极大减少头部体积服务端推送流式传输。这正是 gRPC 选择 HTTP/2 的原因。一次 gRPC 调用 一个 HTTP/2 stream请求/响应都用 trailers 携带 status。3.5 基于 QUICHTTP/3QUIC 基于 UDP解决了 TCP 队头阻塞、连接迁移等问题。gRPC 已实验性支持。3.6 tRPC 的多协议设计tRPC 不绑死任何协议协议是可插拔的默认trpc协议基于 TCPprotobuf可配置 HTTPJSON可与 gRPC 互通也支持自定义协议server:service:-name:trpc.app.server.Helloprotocol:trpc# 切到 grpc / http 改一行四、连接管理4.1 短连接 vs 长连接模式适用短连接调用极少、跨网络层长连接RPC、WebSocket、数据库RPC 默认使用长连接 多路复用。4.2 连接池为目标服务维护一组连接ServiceA → [ conn1, conn2, conn3 ] → ServiceB关键参数max_idle空闲上限max_active活跃上限idle_timeout空闲超时4.3 Keep-Alive定期发送心跳维持长连接、检测半开连接client:keepalive_time:30skeepalive_timeout:10s五、半包与粘包TCP 是面向字节流的没有消息边界。如果应用层不处理就会出现粘包两条消息粘到一起半包一条消息被切成两段。解决方案定长每条消息固定长度适合简单协议分隔符用特殊字节作结束符如 HTTP 用\r\n\r\nTLV/HeaderBody最常用先读固定长度的 headerheader 中带 body 长度再读 body。Protobuf RPC 框架普遍使用第三种。六、流量控制与背压HTTP/2 内置流量控制每个 stream 都有 window接收方处理不过来会让发送方阻塞。tRPC、gRPC 都依赖该机制做反压避免下游被打爆。七、压缩减少带宽消耗但增加 CPU 开销。常见算法算法速度压缩比gzip中中snappy快低zstd较快高lz4极快低gRPC/tRPC 都支持在调用级别启用压缩client.Hello(ctx,req,client.WithCompressType(codec.CompressTypeGzip))八、实战抓包看一次 gRPC 调用# 前置开启 tcpdumpsudotcpdump-ilo0-wgrpc.pcap port9000# 用 wireshark 打开# 设置 HTTP/2 解析Edit Preferences Protocols HTTP2你会看到HTTP/2 帧HEADERS、DATA、TRAILERHEADERS 中的:path /package.Service/MethodDATA 中的 protobuf 字节TRAILER 中的grpc-status: 0。九、序列化性能优化技巧消息池化使用sync.Pool复用 message 对象零拷贝尽量用bytes类型而非string频繁转换批量调用合并多次小调用为一次预分配 slice/map 容量慎用反射protojson 比 json.Marshal 慢优先二进制。十、小结序列化决定数据格式传输协议决定数据怎么走Protobuf 通过 TLVVarintZigZag 实现紧凑高效HTTP/2 是 RPC 的现代标配多路复用解决了队头阻塞解决粘包长度前缀法是工业标准选型时综合考虑性能、可读性、生态。下一篇我们将进入分布式 RPC 的灵魂服务发现与负载均衡。