【GO】31.grpc 클라이언트 부하 분산 소스 코드 분석

이 글은 클라이언트 grpc 로드 밸런싱의 소스코드를 직접 보는 과정을 기록한 글로 너무 자세하게 설명하지 않고 참고가치가 적고 직접 스킵할 수 있는 글입니다. 주로 본인을 위한 글입니다.

1. 메인 인터페이스: 밸런서 리졸버

1.밸런서의 정의

리졸버 정의

구체적인 위치는

1. grpc 소스 코드는 dns, passthrough 및 unix의 세 가지 구조로 resolver(resolver) Builder 인터페이스를 구현합니다. clientconn.go 파일에서 패키지를 참조하여 해당 패키지의 초기화 메소드에 등록

2. internal/resolver/passthrough/passthrough.go 파일에 초기화 초기화 함수를 입력하고 passthroughBuilder가 등록된 것을 확인합니다. resolver 패키지의 Register 기능을 호출합니다.

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

3. Register는 등록된 구조체를 맵인 전역 변수 m에 저장합니다. 키는 Scheme이고 값은 Builder 인터페이스입니다. grpc의 기본 체계는 passthrough입니다. 즉, passthrough는 아무 작업도 수행하지 않습니다.

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. passthroughBuilder를 다시 살펴보고 Buider 인터페이스를 구현하고 Build 메서드가 Resolver 인터페이스를 구현하는 passthroughResolver 구조를 반환하는지 확인합니다. 그 중 passthroughBuilder는 파서를 생성하는데 사용되며, passthroughResolver는 생성된 파서이다.

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. 이 코드에서 반환된 resolverBuilder는 위에서 찾은 등록된 빌더이며 resolver.Get은 1.3의 해당 코드입니다.

7. 파서의 newCCResolverWrapper 패키지를 생성하고 build를 호출하여 파서를 생성합니다. 1. 밸런서 신호를 선택하기 위해 트리거합니다. 2. 트리거 상태 수정(로드 밸런싱, 즉 연결 생성 포함)

위의 switchToUpdate 및 ccStateUpdate를 각각 ccBalancerWrapper의 채널로 보냈습니다.

밸런서 선택 로직

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

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

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

Supongo que te gusta

Origin blog.csdn.net/chen_peng7/article/details/129213025
Recomendado
Clasificación