gRPC 소스 상세 설명 (1) 구성화된 구조체
DialOptions
DialOptions는 가장 중요한 일환으로 매번 rpc 요청을 설정할 때의 선택을 책임진다.
구조
이거의 구조 링크를 먼저 볼게요.
// dialOptions configure a Dial call. dialOptions are set by the DialOption
// values passed to Dial.
type dialOptions struct {
unaryInt UnaryClientInterceptor
streamInt StreamClientInterceptor
chainUnaryInts []UnaryClientInterceptor
chainStreamInts []StreamClientInterceptor
cp Compressor
dc Decompressor
bs backoff.Strategy
block bool
insecure bool
timeout time.Duration
scChan
명명이 매우 규범적이기 때문에, 주석을 더하면 각field가 설정한 어떤 속성을 쉽게 이해할 수 있다.스쳐 지나가면 압축 해압기, 시간 초과 막힘 설정, 인증 안전 전송, 부하 균형, 서비스 영구화 정보 저장, 설정, 심장 박동 검사 등이 있을 것이다.
그 함수 방법은 모두 그 중의 필드를 설정하는 것이다.
설정 방법
여기는grpc디자인이 비교적 좋은 곳으로 함수 설정을 통해 함수를 생성하는 함수를 동시에 설치한다.무슨 뜻이죠?먼저 그림과 결합하여 이해하자면 이것도 전체grpc설정의 정수 부분이다
이 뜻은DialOptions는 내보내기 인터페이스로, 실현 함수는 apply가 매개 변수인 dialOptions를 동시에 받아들여 수정하는 것이다.실제로 new FuncDialOptions 함수를 사용하여 dialOptions를 수정하는 방법으로 funcDialOptions 구조체에 포장하고 실제 Dial을 호출할 때 패키지를 닫아서 funcDialOptions 구조체를 호출하는 apply 방법을 사용한다.여기서 Dial 방법의 원본 코드를 볼 수 있습니다. (Dial은 DialContext가 작용하는opt.apply ()
func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *ClientConn, err error) {
cc := &ClientConn{
target: target,
csMgr: &connectivityStateManager{},
conns: make(map[*addrConn]struct{}),
dopts: defaultDialOptions(),
blockingpicker: newPickerWrapper(),
czData: new(channelzData),
firstResolveEvent: grpcsync.NewEvent(),
}
···
for _, opt := range opts {
opt.apply(&cc.dopts)
}
···
}
이곳의 옵션은 client가 rpc 요청을 하는 핵심 중계소라고 할 수 있다.또 다른 중요한 인터페이스는 다이얼 옵션 구조체에 집중되어 초기화 처리된 것이다
callOptions []CallOption
CallOption CallOption은 rpc 에 정의된 인터페이스입니다.util 패키지 내
구조
// CallOption configures a Call before it starts or extracts information from
// a Call after it completes.
type CallOption interface {
// before is called before the call is sent to any server. If before
// returns a non-nil error, the RPC fails with that error.
before(*callInfo) error
// after is called after the call has completed. after cannot return an
// error, so any failures should be reported via output parameters.
after(*callInfo)
}
조작된 것은callInfo구조의 데이터로
dialOptions
구조체에 포함된다. 즉, 다이얼이 매번 호출될 때마다.callInfo
동시에 그 자체의 정의는 매우 재미있다. 조작된 것은
callInfo
구조체이다.// callInfo contains all related configuration and information about an RPC.
type callInfo struct {
compressorType string
failFast bool
stream ClientStream
maxReceiveMessageSize *int
maxSendMessageSize *int
creds credentials.PerRPCCredentials
contentSubtype string
codec baseCodec
maxRetryRPCBufferSize int
}
압축, 흐름 제어, 인증, 디코더 등 단일 호출에 사용되는 사용자 정의 옵션을 볼 수 있습니다.
하나의 실현
Call Option 인터페이스의 구현을 간단히 살펴보십시오.
// Header returns a CallOptions that retrieves the header metadata
// for a unary RPC.
func Header(md *metadata.MD) CallOption {
return HeaderCallOption{HeaderAddr: md}
}
// HeaderCallOption is a CallOption for collecting response header metadata.
// The metadata field will be populated *after* the RPC completes.
// This is an EXPERIMENTAL API.
type HeaderCallOption struct {
HeaderAddr *metadata.MD
}
func (o HeaderCallOption) before(c *callInfo) error { return nil }
func (o HeaderCallOption) after(c *callInfo) {
if c.stream != nil {
*o.HeaderAddr, _ = c.stream.Header()
}
}
실제 작업은 before와 애프터 방법에서 실행되며 클라이언트가 요청을 할 때 자동으로 실행됩니다. 말 그대로 하나는 호출하기 전에 실행하고 하나는 호출 후에 실행합니다.
주의 실현
여기서 알 수 있듯이 여기도 함수를 통해 이 두 가지 방법을 가진 구조체를 되돌려준다. 이 디자인에 주의하면 너 자신의 Option이 디자인할 때 참고할 수 있다.
두 가지 방법
Client가 당신의 Call Option 설정을 받아들일 수 있는 두 가지 방법이 있습니다.
// WithDefaultCallOptions returns a DialOption which sets the default
// CallOptions for calls over the connection.
func WithDefaultCallOptions(cos ...CallOption) DialOption {
return newFuncDialOption(func(o *dialOptions) {
o.callOptions = append(o.callOptions, cos...)
})
}
좀 이해가 안 가죠?실례를 하나 드릴게요.
response, err := myclient.MyCall(ctx, request, grpc.CallContentSubtype("mycodec"))
myclient := grpc.Dial(ctx, target, grpc.WithDefaultCallOptions(grpc.CallContentSubtype("mycodec")))
여기에 mycodec 디코더를 설치했다고 가정하십시오.바로 아래에 그것의 설계를 설명하시오.
달리
주의해야 할 것은 내가 단지 클라이언트 호출 시 설정만 언급한 것 같은데,callOption이 클라이언트 설정에만 있는 상황이 모두를 곤혹스럽게 하는 것 아니냐는 것이다.실제로 gRPC 서버 측은 자동으로callOption의 설정을 검사하고 이 선택을 지원하는지 확인합니다. 지원하지 않으면 실패로 돌아갑니다.서버에서 등록된 모든 코덱 디코더를 설치한 후 클라이언트가 해당 설정을 직접 사용하면 된다는 것이다.
Codec
gRPC에서 코드는 두 개의 인터페이스 정의가 있는데 하나는 베이스 코드가 정상적인 Marshal과 Unmarshal 방법을 포함하고 다른 하나는 이름을 가진 코드가 encoding 패키지에 정의된 것이다. 이것은registry를 등록할 때 이 방법을 사용하기 때문이다.
이음매
type Codec interface {
// Marshal returns the wire format of v.
Marshal(v interface{}) ([]byte, error)
// Unmarshal parses the wire format into v.
Unmarshal(data []byte, v interface{}) error
// String returns the name of the Codec implementation. This is unused by
// gRPC.
String() string
}
이 방법입니다.
// RegisterCodec registers the provided Codec for use with all gRPC clients and
// servers.
//
// The Codec will be stored and looked up by result of its Name() method, which
// should match the content-subtype of the encoding handled by the Codec. This
// is case-insensitive, and is stored and looked up as lowercase. If the
// result of calling Name() is an empty string, RegisterCodec will panic. See
// Content-Type on
// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for
// more details.
//
// NOTE: this function must only be called during initialization time (i.e. in
// an init() function), and is not thread-safe. If multiple Compressors are
// registered with the same name, the one registered last will take effect.
func RegisterCodec(codec Codec) {
if codec == nil {
panic("cannot register a nil Codec")
}
if codec.Name() == "" {
panic("cannot register Codec with empty string result for Name()")
}
contentSubtype := strings.ToLower(codec.Name())
registeredCodecs[contentSubtype] = codec
}
Compressor
또한 encoding 패키지에Compressor 인터페이스가 정의되어 있으므로 Codec를 참조하여 이해하면 됩니다.
// Compressor is used for compressing and decompressing when sending or
// receiving messages.
type Compressor interface {
// Compress writes the data written to wc to w after compressing it. If an
// error occurs while initializing the compressor, that error is returned
// instead.
Compress(w io.Writer) (io.WriteCloser, error)
// Decompress reads data from r, decompresses it, and provides the
// uncompressed data via the returned io.Reader. If an error occurs while
// initializing the decompressor, that error is returned instead.
Decompress(r io.Reader) (io.Reader, error)
// Name is the name of the compression codec and is used to set the content
// coding header. The result must be static; the result cannot change
// between calls.
Name() string
}
MetaData
이 패키지는 context의Value field, 즉 키-value 형식의 저장소에 대응합니다
다른 가방에 MD라고 간략하게 적었어요.
구조
type MD map[string][]string
함수.
완벽한 저장 기능을 실현하여 단일 읽기에서 대량 읽기(pair 모드를 사용하고...string을 매개 변수로 하고len(string)%2==1일 때 오류가 발생합니다. 짝이 없는 원 정보가 고립되기 때문입니다.
다른 몇 가지 함수는 context에서 읽기와 쓰기를 실현했습니다. (여기 쓰기는 context.WithValue 방법을 사용합니다.parent context를 생성하는copy입니다.
주의⚠️
type mdIncomingKey struct{}
type mdOutgoingKey struct{}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
gRPC 소스 상세 설명 (1) 구성화된 구조체이 뜻은DialOptions는 내보내기 인터페이스로, 실현 함수는 apply가 매개 변수인 dialOptions를 동시에 받아들여 수정하는 것이다.실제로 new FuncDialOptions 함수를 사용하여 dialO...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.