【GO】31.grpc client load balancing source code analysis

This article is to record the process of viewing the source code of the client grpc load balancing. It does not explain in too much detail. It is of little reference value and can be skipped directly. It is mainly for yourself.

1. Main interface: Balancer Resolver

1.Definition of Balancer

Resolver definition

The specific location is

1. The grpc source code implements the resolver (resolver) Builder interface with three structures: dns, passthrough, and unix. Registered in the initialization method of the corresponding package by referencing the package in the clientconn.go file

2. Enter the init initialization function in the internal/resolver/passthrough/passthrough.go file and see that the passthroughBuilder has been registered. The Register function of the resolver package is called

func init() {
    resolver.Register(&passthroughBuilder{})
}

3. Register saves the registered structure in the global variable m, which is a map. The key is Scheme, and the value is the Builder interface. We see that the default scheme of grpc is passthrough, that is, passthrough does nothing

package resolver

import (
    "context"
    "net"
    "net/url"
    "strings"

    "google.golang.org/grpc/attributes"
    "google.golang.org/grpc/credentials"
    "google.golang.org/grpc/internal/pretty"
    "google.golang.org/grpc/serviceconfig"
)

var (
    // m is a map from scheme to resolver builder.
    m = make(map[string]Builder)
    // defaultScheme is the default scheme to use.
    defaultScheme = "passthrough"
)

// TODO(bar) install dns resolver in init(){}.

// Register registers the resolver builder to the resolver map. b.Scheme will be
// used as the scheme registered with this builder.
//
// NOTE: this function must only be called during initialization time (i.e. in
// an init() function), and is not thread-safe. If multiple Resolvers are
// registered with the same name, the one registered last will take effect.
func Register(b Builder) {
    m[b.Scheme()] = b
}

// Get returns the resolver builder registered with the given scheme.
//
// If no builder is register with the scheme, nil will be returned.
func Get(scheme string) Builder {
    if b, ok := m[scheme]; ok {
        return b
    }
    return nil
}

4. Look at passthroughBuilder again, and see that it implements the Buider interface, and the Build method returns the structure passthroughResolver that implements the Resolver interface. Among them, passthroughBuilder is used to create a parser, and passthroughResolver is the created parser

package passthrough

import (
    "errors"

    "google.golang.org/grpc/resolver"
)

const scheme = "passthrough"

type passthroughBuilder struct{}

func (*passthroughBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (resolver.Resolver, error) {
    if target.Endpoint() == "" && opts.Dialer == nil {
        return nil, errors.New("passthrough: received empty target in Build()")
    }
    r := &passthroughResolver{
        target: target,
        cc:     cc,
    }
    r.start()
    return r, nil
}

func (*passthroughBuilder) Scheme() string {
    return scheme
}

type passthroughResolver struct {
    target resolver.Target
    cc     resolver.ClientConn
}

func (r *passthroughResolver) start() {
    r.cc.UpdateState(resolver.State{Addresses: []resolver.Address{
    
    {Addr: r.target.Endpoint()}}})
}

func (*passthroughResolver) ResolveNow(o resolver.ResolveNowOptions) {}

func (*passthroughResolver) Close() {}

func init() {
    resolver.Register(&passthroughBuilder{})
}

5. The resolverBuilder returned in this code is the registered builder found above, and resolver.Get is the corresponding code in 1.3

7. Generate the package newCCResolverWrapper of the parser, and call build to create the parser. In this process, the start method of the parser is called. The more important thing about this method is that it does two things. 1. Trigger to select the balancer signal. 2. Trigger state modification (including load balancing, that is, connection creation)

The above sent switchToUpdate and ccStateUpdate to the channel of ccBalancerWrapper respectively

balancer selection logic

baseBalancer会将所有地址都创建一个连接

invoke的时候,会调用picker选择连接

以上路径最终调用这个方法,可以看到是轮询使用连接

Guess you like

Origin blog.csdn.net/chen_peng7/article/details/129213025