grpc 源码阅读之 balancer

Balancer

gRPC balancer

背景

接着上篇《gRPC 插件式编程之Resolver》,gRPC 将 target 解析为 resolver.Target 后,通过 resolver.Builder.Build 方法调用
resolver.ClientConn.UpdateState(State) error 方法,该方法做了哪些事情呢,我们本篇接着看源码往下走。

UpdateState

UpdateState 的调用会调用 grpc.ClientConn.updateResolverState 方法,该方法主要做了如下工作:

  • ServiceConfig 处理
  • BalancerWrapper 创建
  • 调用 balancer.updateClientConnState 方法 执行负载均衡逻辑更新
func (cc *ClientConn) updateResolverState(s resolver.State, err error) error {
   
    ...
    cc.maybeApplyDefaultServiceConfig(s.Addresses)
    ...
    cc.applyServiceConfigAndBalancer(sc, configSelector, s.Addresses)
    ...
    // reference: balancer_conn_wrappers.go:164
    // bw.updateClientConnState -> ccBalancerWrapper.updateClientConnState
    bw.updateClientConnState(&balancer.ClientConnState{
   ResolverState: s, BalancerConfig: balCfg})
    ...
}

温馨提示

这里先以搞懂 gRPC 主流程思路为主,不扣太细节的东西,比如一些 GRPCLB 处理、error处理,ServiceConfigSelector 处理等可以查看源码。

bw.updateClientConnState 调用本质是 ccBalancerWrapper.updateClientConnState
ccBalancerWrapper.updateClientConnState 就做了一件事情,调用 balancer.Balancer.UpdateClientConnState 方法

func (ccb *ccBalancerWrapper) updateClientConnState(ccs *balancer.ClientConnState) error {
   
    ccb.balancerMu.Lock()
    defer ccb.balancerMu.Unlock()
    return ccb.balancer.UpdateClientConnState(*ccs)
}

到这里,我们想看 balancer 源码逻辑有两种途径

  • 自己实现的 balancer.Balancer
  • gRPC 提供的 balancer

为了阅读源码,我们先去阅读 gRPC 提供的几个 balancer 中的一个进行流程理解,后续再介绍如何自定义一个 balancer

gRPC Balancer

gRPC 提供了几个负载均衡处理,如下:

  • grpclb
  • rls
  • roundrobin
  • weightroundrobin
  • weighttarget

为了好理解,我们挑一个简单的负载均衡器 roundrobin 继续阅读。

负载均衡从哪里获取?通过前面 cc.maybeApplyDefaultServiceConfig(s.Addresses) 方法中的源码可知,balancer.Balancerbalancer.Builder
提供,我们看一下 balancer.Builder 接口

// Builder creates a balancer.
type Builder interface {
   
    // Build creates a new balancer with the ClientConn.
    Build(cc ClientConn, opts BuildOptions) Balancer
    // Name returns the name of balancers built by this builder.
    // It will be used to pick balancers (for example in service config).
    Name() string
}

roundrobin

roundrobin 是 gRPC 内置的负载均衡器,其和 resolver 一样都是通过插件式编程提供扩展,在源码中,我们可知,
roundrobin 在 init 函数中对 balancer.Builder 进行了注册,其中 baseBuilderbalancer.Builder 的实现,
上文我们得知, balancer.Balancerbalancer.Builder.Build 提供,通过 baseBuilder.Build 方法我们知道 gRPC 的
balancer 底层是由 baseBalancer 实现,部分源码如下:

roundrobin.go

// newBuilder creates a new roundrobin balancer builder.
func newBuilder() balancer.Builder {
   
    return base.NewBalancerBuilder(Name, &rrPickerBuilder{
   }, base.Config{
   HealthCheck: true})
}

func init() {
   
    balancer.Register(newBuilder())
}

balancer.go

func (bb *baseBuilder) Build(cc balancer.ClientConn, opt balancer.BuildOptions) balancer.Balancer {
   
    bal := &baseBalancer{
   
        cc:            cc,
        pickerBuilder: bb.pickerBuilder,
    
        subConns: resolver.NewAddressMap(),
        scStates: make(map[balancer.SubConn]connectivity.State),
        csEvltr:  &balancer.ConnectivityStateEvaluator{
   },
        config:   bb.config,
    }
    bal.picker = NewErrPicker(balancer.ErrNoSubConnAvailable)
    return bal
}

沿着 UpdateState 环节最后一个方法 ccb.balancer.UpdateClientConnState(*ccs) 调用阅读,其实最终来到了
baseBalancer.UpdateClientConnState 方法,我们查看一下源码:

func (b *baseBalancer) UpdateClientConnState(s balancer.ClientConnState) error {
   
    ...
    addrsSet := resolver.NewAddressMap()
    for _, a := range s.ResolverState.Addresses {
   
        addrsSet.Set(a, nil)
        if _, ok := b.subConns.Get(a); !ok {
   
            sc
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值