Go语言net/rpc需自行实现负载均衡:轮询适用于静态节点,加权随机适配异构节点,一致性哈希减少扩缩容抖动,结合服务发现与健康探测提升生产可靠性。

Go 语言原生 net/rpc 不内置负载均衡能力,需在客户端或中间层自行实现。核心思路是:将多个 RPC 服务节点抽象为可选后端池,根据策略选择目标节点发起调用。关键在于解耦服务发现、健康检查与路由逻辑,避免单点瓶颈和请求倾斜。
基于客户端的轮询(Round-Robin)均衡
最简单且无依赖的方案:客户端维护一个服务地址列表,每次调用时按顺序选取下一个节点。适合服务节点静态、数量较少、不频繁变更的场景。
- 用
sync/atomic管理递增索引,保证并发安全 - 初始化时预热连接(如提前 Dial 并缓存 *rpc.Client),避免每次新建开销
- 遇到调用失败(如连接拒绝、超时),跳过该节点并标记短暂不可用(例如 30 秒),不立即重试同一节点
加权随机(Weighted Random)适配异构节点
当后端节点 CPU、内存或网络带宽差异较大时,单纯轮询会导致强节点闲置、弱节点过载。可为每个节点配置权重(如 1–10),按权重比例决定被选中的概率。
- 构建权重累积数组:[w₁, w₁+w₂, w₁+w₂+w₃, …],生成 [0, sum) 区间随机数,二分查找落入区间
- 权重可动态更新(如通过配置中心推送),但需加锁保护数组重建过程
- 建议结合响应延迟反馈自动调整权重:某节点 P95 延迟持续升高,则临时下调其权重 20%
一致性哈希减少节点变动影响
适用于需保持“相同请求打到同一节点”的场景(如带本地缓存或会话状态的 RPC 服务)。新增/下线节点时,仅少量 key 重新映射,避免全量抖动。
立即学习“go语言免费学习笔记(深入)”;
- 对请求参数(如用户 ID、订单号)做哈希,再对虚拟节点环取模;虚拟节点数建议设为物理节点数 × 100+
- Go 可用
github.com/hashicorp/go-memdb或轻量库github.com/bradfitz/gomemcache/memcache中的一致性哈希逻辑复用 - 注意:若参数本身分布不均(如大量 0 值 ID),需加盐(salt)再哈希,提升散列均匀性
集成服务发现与健康探测
真实生产环境节点常动态扩缩容,硬编码地址不可靠。应对接 Consul、etcd 或 Nacos,实现自动注册与剔除。
- 客户端监听服务实例列表变更(watch),收到更新后原子替换本地 backend 列表
- 后台 goroutine 定期对每个节点发起轻量探测(如 TCP 连通性 + 自定义 /health RPC 方法),连续 3 次失败则从可用池移除
- 探测结果可与熔断器(如
sony/gobreaker)联动:某节点错误率 > 50%,自动开启熔断,暂停分配新请求










