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
    评论
GRPC是一种高性能、开源、通用的RPC框架。它基于HTTP/2协议标准设计,支持多种编程语言。在Java中,GRPC提供了完整的Java API和工具链。 下面是GRPC Java源码分析的一些关键点: 1. 服务定义:GRPC使用Protocol Buffers(protobuf)作为服务定义语言。通过编写.proto文件,定义服务接口和数据结构。 2. 代码生成:使用protobuf编译器生成Java代码,包括服务接口和数据结构的类定义、序列化和反序列化方法等。 3. 服务实现:实现服务接口的方法,完成实际的业务逻辑。GRPC支持两种类型的服务:普通服务和流式服务。普通服务是一次请求-响应的模式,流式服务则可以支持客户端和服务端之间的多次交互。 4. 服务绑定:将服务实现绑定到GRPC服务器上。GRPC提供了一个ServerBuilder类来创建和配置GRPC服务器。 5. 客户端调用:使用GRPC提供的客户端Stub类,调用服务接口中的方法。GRPC客户端支持同步和异步两种调用方式,以及流式调用。 6. 传输协议:GRPC使用HTTP/2作为传输协议。HTTP/2提供了流控制、头部压缩、多路复用等特性,可以提高网络传输效率和性能。 7. 序列化和反序列化:GRPC使用protobuf作为序列化和反序列化的工具。protobuf提供了高效的二进制序列化和反序列化方法,可以减少数据传输量和网络延迟。 总之,GRPC Java源码分析需要理解上述关键点,并深入了解GRPC的底层实现原理和机制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值