RPC 核心概念 04:服务发现与负载均衡
RPC 核心概念 04服务发现与负载均衡单机时代我们靠 IPPort 直连微服务时代服务实例数动辄几十上百IP 还会频繁变化。服务发现 负载均衡就是解决我该把请求发到哪里的核心机制。一、问题的提出调用方client:NewUserClient(user.example.com:8000)resp,_:client.GetUser(ctx,req)直连有以下问题实例 IP 变化容器重启、扩容单点故障流量无法均衡到多个实例实例上下线无法感知。解决思路在客户端和服务实例之间引入服务注册中心和负载均衡器。二、服务发现的两种模式2.1 客户端发现Client-side Discovery[ Registry ] ↑ | | 注册 | 查询 | ↓ [ Service A实例 ] [ Client ] ──直连──► [ Service A 实例 N ]特点Client 直接查注册中心拿到实例列表LB 算法在 Client 侧性能好少一跳但所有客户端都要集成 SDK。代表Netflix Ribbon、gRPC、tRPC、Dubbo。2.2 服务端发现Server-side Discovery[ Service A实例 ] → [ Registry ] ↑ [ Client ] → [ LB / Sidecar ] → [ Service A 实例 N ]特点LB 是独立组件可能是 nginx、Envoy、k8s ServiceClient 只知道 LB 的入口多语言成本低但多一跳。代表k8s Service kube-proxy / Istio Sidecar、AWS ALB。2.3 现代趋势Service Mesh把客户端发现改造为Sidecar 拦截 客户端发现业务代码无感知。三、注册中心的角色注册中心负责服务注册实例启动后上报 IP、端口、元数据健康检查周期 ping剔除不健康节点服务订阅客户端订阅变化实时更新本地缓存元数据管理版本、环境、机房等。3.1 主流注册中心名称特点Consul多数据中心、KV、健康检查丰富etcdk8s 自带、强一致RaftZooKeeper老牌、CP 系统、运维较重Nacos阿里开源配置 注册一体EurekaNetflixAP 系统已停止维护Polaris北极星腾讯开源tRPC 默认搭档3.2 CAP 取舍CP强一致可能不可用ZooKeeper、etcdAP高可用可能不一致Eureka、Nacos、Polaris。服务发现场景优先 AP——短暂列表不一致比注册中心宕机带来的损失小得多。3.3 Polaris 简介Polaris北极星是腾讯开源的服务治理平台集注册发现 配置 路由 限流熔断 可观测于一体是 tRPC 体系的默认服务治理中枢。其核心 APIimportgithub.com/polarismesh/polaris-go/apiprovider,_:api.NewProviderAPI()provider.Register(api.InstanceRegisterRequest{Service:trpc.app.user,Namespace:Production,Host:10.0.0.1,Port:8000,})consumer,_:api.NewConsumerAPI()resp,_:consumer.GetOneInstance(api.GetOneInstanceRequest{Service:trpc.app.user,})四、负载均衡算法4.1 静态算法轮询Round Robin请求1 → A 请求2 → B 请求3 → C 请求4 → A简单公平但忽略实例性能差异。加权轮询Weighted Round Robin为每个实例配置权重如 CPU 多的权重大按比例分配。Nginx 的默认算法。随机Random请求量大时表现接近轮询实现简单无状态。哈希Hash按某个 key如用户 ID哈希到实例保证同一用户落到同一实例常用于带本地缓存或会话粘性场景。4.2 动态算法最少连接Least Connections把请求发给当前连接数最少的实例自动避开慢节点。P2C / EWMA指数加权移动平均随机选两个实例比较各自负载连接数、最近平均延迟选好的那个。简单高效Google SRE 推荐。一致性哈希Consistent Hashing哈希环 虚拟节点实例增减时只影响相邻段。常用于缓存系统Redis Cluster大对象存储路由。4.3 算法选择场景推荐实例性能均匀轮询/随机实例性能不均匀加权轮询 / P2C会话粘性哈希 / 一致性哈希带状态缓存一致性哈希长连接服务最少连接五、健康检查5.1 客户端主动探测healthCheck:type:tcp / http / grpcinterval:5stimeout:2sthreshold:3# 连续失败次数5.2 服务端被动上报实例自己定期向注册中心发心跳实例 ──5s 一次心跳──► 注册中心超过 N 个周期未收到则剔除。5.3 熔断式被动探测调用失败率达到阈值本地标记节点不健康停发流量一段时间过会儿再试探。六、动态路由除了哪个实例可用还有该把请求送到哪个实例。6.1 元数据路由每个实例打标签version、env、region按标签匹配routes:-match:header:x-canary:trueroute:version:v2# 灰度6.2 就近路由按机房/区域优先Beijing-Client ─prefer→ Beijing-实例 ─fallback→ Shanghai-实例6.3 流量染色用户/请求带染色 tag整个调用链都按染色规则路由是全链路灰度的基石。七、tRPC-Go 中的实现tRPC 通过插件实现服务发现 负载均衡 路由client:service:-name:trpc.app.usertarget:polaris://trpc.app.userprotocol:trpcloadbalance:weighted_randomdiscovery:polaris代码层面proxy:pb.NewUserClientProxy(client.WithTarget(polaris://trpc.app.user),client.WithBalancerName(p2c),)resp,err:proxy.GetUser(ctx,req)整个发现 选路 调用过程对业务完全透明。八、缓存与同步客户端不可能每次调用都查注册中心必须本地缓存启动时 → 拉取全量 之后 → 监听增量变更watch / push 失败 → 降级到上次的缓存降级缓存至关重要——注册中心宕机时业务还能继续跑。九、灰度与金丝雀借助元数据路由实现部署 v2 版本权重设为 5%监控 v2 错误率/延迟没问题逐步放量出问题立即把 v2 权重设为 0。十、踩坑总结依赖回环注册中心也需要服务发现要避免循环依赖网络分区注册中心心跳超时不一定真挂了缓存雪崩注册中心抖动导致全量重连慢启动新实例上线先少量流量预热权重突变避免直接 0 → 100渐进调权重。十一、小结服务发现解决调谁负载均衡解决调多个中的哪一个客户端发现性能好但有 SDK 依赖服务端发现简单但多一跳注册中心选型服务发现场景偏好 APLB 算法没有银弹按场景选tRPC Polaris 是国产工业级实践代表。下一篇我们将探讨 RPC 服务治理三大件超时、重试与熔断。