Go语言RPC性能优化需从序列化、连接复用、并发控制和服务端细节入手:1. 用protobuf替代gob,或接入msgpack/cbor提升编解码效率;2. 全局复用rpc.Client,配置KeepAlive和连接池减少建连开销;3. 使用context超时控制和semaphore限制并发,防止雪崩;4. 服务端精简注册方法、预分配响应对象、使用sync.Pool降低GC压力,关闭冗余日志以减少I/O瓶颈。

Go语言的RPC调用性能优化,核心在于减少序列化开销、降低网络延迟影响、提升并发处理能力,以及避免运行时瓶颈。不改协议、不换框架的前提下,很多优化点能立竿见影。
用更轻量的序列化协议替代默认 gob
Go标准库net/rpc默认使用gob编码,它类型安全但性能一般,体积大、编码/解码慢。生产环境建议切换为json(简单场景)或更优的Protocol Buffers(推荐)。
- 使用
gRPC-Go(底层基于protobuf + HTTP/2),天然支持流式、压缩、连接复用 - 若仍用
net/rpc,可自定义rpc.ServerCodec和rpc.ClientCodec接入msgpack或cbor,实测比gob快2–5倍,载荷小30%–60% - 避免在结构体中嵌套大量指针或interface{},会显著拖慢gob反射序列化;优先用具体类型+omitempty tag精简字段
复用连接与客户端,避免频繁建连
RPC本质是网络调用,TCP握手、TLS协商、连接初始化都是开销。每次请求都新建*rpc.Client等于反复“从零开始”。
- 全局复用一个
*rpc.Client实例(注意它本身是goroutine-safe的) - 使用长连接:对
http.Transport(gRPC)或net.Dialer(自定义TCP RPC)配置KeepAlive、MaxIdleConns、MaxIdleConnsPerHost - 服务端用
rpc.ServeConn配合连接池管理已建立的TCP连接,而非对每个新连接都起新goroutine
合理控制并发与超时,防止雪崩
无限制并发调用会压垮服务端或耗尽本地资源(文件描述符、内存、goroutine栈);缺乏超时则导致请求堆积、级联失败。
立即学习“go语言免费学习笔记(深入)”;
- 客户端侧用
context.WithTimeout或context.WithDeadline强制约束单次调用生命周期 - 用
semaphore(如golang.org/x/sync/semaphore)限制最大并发请求数,尤其在批量调用场景 - 服务端开启
runtime.GOMAXPROCS合理设置,并监控runtime.NumGoroutine(),避免goroutine泄漏(比如忘记defer resp.Body.Close())
服务端做针对性优化:注册精简、响应预分配、日志降级
服务端的微小开销在高QPS下会被放大。几个易忽略但有效的点:
- 只注册真正需要导出的方法,避免
rpc.Register传入过大结构体——它会反射遍历所有可导出字段和方法 - 对高频小响应接口,提前分配好
struct或[]byte,避免每次调用都触发GC(可用对象池sync.Pool管理常用响应结构) - 关闭调试日志或分级输出(如用
log.SetFlags(0)去掉时间戳前缀),日志I/O在高并发下可能成为瓶颈
基本上就这些。不需要大动架构,从序列化、连接、并发、服务端四方面逐项检查,多数Go RPC服务的P99延迟能下降40%以上,吞吐翻倍也很常见。











