Go原生net/rpc不支持负载均衡,需结合客户端选节点逻辑与服务端注册发现机制实现;核心是将节点选择前移到客户端,支持轮询、随机、最少连接、加权等策略,并依赖etcd等注册中心实现服务发现与健康探测。
Go 语言原生 net/rpc 不支持负载均衡,但通过组合客户端选节点逻辑 + 服务端注册/发现机制,可以构建轻量、可控的 RPC 负载均衡系统。核心在于把“找哪个服务实例处理请求”这件事,从服务端(如 Nginx)前移到客户端或中间协调层,提升灵活性与实时性。
客户端维护一份可用服务地址列表(例如从 Consul/Etcd/ZooKeeper 拉取,或静态配置),每次调用前按策略选择一个节点发起 RPC 连接。
示例片段(轮询):
var ( addrs = []string{"192.168.1.10:8080", "192.168.1.11:8080"} mu sync.RWMutex idx uin
t64
)
func nextAddr() string {
mu.Lock()
defer mu.Unlock()
addr := addrs[idx%uint64(len(addrs))]
idx++
return addr
}
服务启动时向注册中心(如 etcd)写入自身地址和元数据(版本、权重、标签),并定期续租(TTL)。客户端监听变更或定时拉取,自动剔除失联节点。
clientv3(etcd 官方 Go SDK)注册:写入 /services/rpc-service/192.168.1.10:8080,设置 TTL=30s/health),避免阻塞 RPC 主流程{"weight": 10, "zone": "shanghai"},供客户端做路由决策若项目允许升级协议,gRPC 原生支持客户端负载均衡插件(balancer.Builder),比原生 net/rpc 更成熟:
grpc.WithBalancerName("round_robin") 启用内置策略Resolver 实现服务发现(对接 etcd/Consul),动态更新后端地址列表grpc.WithKeepaliveParams 和重试策略,提升弱网下稳定性相比手撸 net/rpc 均衡逻辑,gRPC 生态更完善、TLS/流控/超时控制更精细,中小规模服务推荐优先采用。
*rpc.Client 或 gRPC *grpc.ClientConn,避免频繁建连开销基本上就这些。不复杂但容易忽略的是健康状态同步延迟和连接池管理——这两项做好,负载均衡才真正可靠。