服务发现与负载均衡
如何把服务名解析为可调用实例?
- Server:
server.WithRegistry+WithServerBasicInfo; - Client:
client.WithResolver,service name 作为查询键; - 直连: 已知地址时跳过发现; 适合本地开发、诊断与固定依赖;
- 实例元数据: zone、版本、权重、标签可参与路由与均衡;
registry, err := etcd.NewEtcdRegistry([]string{"127.0.0.1:2379"})
if err != nil {
return fmt.Errorf("create registry: %w", err)
}
svr := userservice.NewServer(
new(UserServiceImpl),
server.WithRegistry(registry),
server.WithServerBasicInfo(&rpcinfo.EndpointBasicInfo{ServiceName: "user"}),
)
如何选择负载均衡算法?
- WeightedRoundRobin: 默认策略; 按权重轮询;
- WeightedRandom: 按权重随机; 大样本下趋于均衡;
- ConsistentHash: 相同 key 尽量命中相同实例; 适合有状态或缓存亲和;
- Tagging Based: 根据标签筛选与路由多态实例;
- 自定义: 实现 LoadBalancer 接口,并通过 Client Option 注入;
如何处理实例列表变化?
- 服务名: 注册与发现两端必须一致;
- 更新: Resolver 必须处理新增、删除和权重变化;
- 空实例: 明确 fail-fast、缓存旧值或降级策略;
- 一致性哈希: key 不能为空,虚拟节点越多越均匀但构建成本越高;
- K8s DNS: ClusterIP 只暴露一个地址时,Client 无法感知 Pod 级实例并做严格负载均衡;
如何选择服务发现适配器?
- 选择入口: 第三方集成 汇总注册发现适配器及版本约束;
- 本层职责: 无论控制面选什么产品,Client 最终都需要可用实例、权重和元数据;不要把业务代码绑定到控制面 SDK;