Go 语言 net/rpc 默认不支持压缩,但可通过包装 net.Conn 实现 gzip 压缩传输;需服务端用 gzip.NewReader、客户端用 gzip.NewWriter,并统一压缩级别、避免小消息压缩,或直接采用原生支持 gzip 的 gRPC。
Go 语言标准库的 net/rpc 默认不支持消息压缩,但可以通过包装底层连接(如 net.Conn)实现请求和响应的自动压缩传输,从而显著降低带宽消耗。关键在于在客户端和服务端分别对数据流进行压缩/解压,且需保证两端算法一致、协议兼容。
最常用且高效的方式是用 gzip.Reader 和 gzip.Writer 包装 TCP 连接。服务端接收时解压,客户端发送时压缩——但注意:net/rpc 的 HTTP 模式和自定义 TCP 模式处理方式不同,推荐使用纯 TCP 方式以获得完全控制权。
gzip.NewReader(conn) 包装读取器,再传给 rpc.ServeConn
gzip.NewWriter(conn) 包装写入器,再调用 rpc.NewClient 并替换其内部的 WriteCloser
gzip.Writer 需手动调用 Flush() 或 Close() 才会真正写出压缩数据,否则 RPC 消息可能卡住为避免每次手动包装,可封装一个支持压缩的 CompressClient 和 CompressServer。核心是实现自定义的 io.ReadWriteCloser,内部持有一个原始连接和一个 gzip writer/reader,并重写 Read/Write/Close 方法。
accept 循环中,对每个 conn 构造 &compressConn{conn: conn},其中 Read 调用 gzip.NewReader(conn).Read
&compressConn{conn: conn},其 Write 方法用 gzip.NewWriter 缓冲并自动 Flush
如 gzip.BestSpeed),兼顾性能与压缩率RPC 压缩不是透明的,需确保两端行为严格对齐,否则会出现粘包、EOF 或解压失败等问题。
Compressed:true 的握手 header)若项目允许升级协议,gRPC 原生支持 gzip 编码(通过 grpc.UseCompressor 和 grpc.WithCompressor)。它在 HTTP/2 层自动处理压缩协商与透传,比手撸更健壮,也支持 per-call 控制。
grpc.NewServer(grpc.KeepaliveParams(...), grpc.UseCompressor(gzip.Compressor))
grpc.Dial(..., grpc.WithCompressor(gzip.Compressor))
grpc.EmptyCallOption 实现按需压缩,比如只对大文件上传启用