Go RPC性能优化核心是减少序列化开销、降低网络往返、避免阻塞I/O及合理并发控制;推荐gRPC+Protobuf或MsgPack替代Gob,复用连接,批量合并请求,异步调用,并精简服务端逻辑。

Go 的 RPC 性能优化核心在于减少序列化开销、降低网络往返、避免阻塞式 I/O,并合理控制并发与资源复用。默认的 net/rpc(基于 Gob)在高并发低延迟场景下容易成为瓶颈,需针对性调整。
使用更高效的序列化协议
Gob 编码体积大、解析慢,且不支持跨语言。生产环境推荐切换为 Protocol Buffers(gRPC)或 MsgPack:
- gRPC + Protobuf:二进制紧凑、多语言支持、内置流控与连接复用,延迟通常比 Gob 低 30%~50%
- MsgPack:轻量级二进制格式,兼容 JSON 接口习惯,
go-codec/msgpack库可直接替换 Gob 编解码器,无需改业务逻辑 - 避免在 RPC 参数中传递大结构体或原始字节切片;优先传 ID 或摘要,由服务端按需加载
复用连接与客户端实例
每次调用新建 TCP 连接会引入三次握手和 TLS 握手(如启用 HTTPS),显著增加延迟。应全局复用连接:
- gRPC 客户端是线程安全的,创建一次即可长期复用;设置
WithTransportCredentials或WithInsecure后,内部自动维护连接池 - 若用自定义 HTTP/JSON-RPC,用
http.Client并配置Transport.MaxIdleConns和MaxIdleConnsPerHost(建议 ≥200) - 避免在 handler 内 new client;将 client 作为依赖注入或全局变量初始化
异步调用与批量合并
对非强实时依赖的请求,可聚合多个小请求为单次批量调用,减少网络往返次数:
立即学习“go语言免费学习笔记(深入)”;
- 设计
BatchGet([]string keys) ([]*Item, error)类接口,服务端并行查 DB/Cache,再统一返回 - 使用
context.WithTimeout控制整体超时,而非每个子请求单独设超时 - 对非关键路径,考虑用 channel + goroutine 异步触发 RPC,主流程不等待结果(注意错误处理和重试策略)
精简服务端处理逻辑
RPC 延迟不仅来自网络,也来自服务端 CPU 占用过高导致排队:
- 禁用反射式参数解包(如
net/rpc默认行为);改用 codegen 方式(如 gRPC 的protoc-gen-go)提前生成编解码函数 - 服务端 handler 中避免同步写日志、调用未缓存的外部 API、或执行长循环;耗时操作放入 worker pool(如
ants或自建 goroutine 池) - 开启 pprof,在压测时采集
/debug/pprof/profile?seconds=30,定位 CPU 热点(常见于 JSON 解析、Gob decode、锁竞争)











