当前位置:首页 >> 中药养生 >> grpc 链接池(6)确保安全的设置和传递

grpc 链接池(6)确保安全的设置和传递

发布时间:2024-01-13

newClientStreamWithParams(ctx, desc, cc, method, mc, onCommit, done, opts...) } rpcConfig, err := cc.safeConfigSelector.SelectConfig(rpcInfo)func newClientStreamWithParams(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, mc serviceconfig.MethodConfig, onCommit, doneFunc func(), opts ...CallOption) (_ iresolver.ClientStream, err error) { if mc.Timeout != nil && *mc.Timeout>= 0 { ctx, cancel = context.WithTimeout(ctx, *mc.Timeout) } else { ctx, cancel = context.WithCancel(ctx) }

可以想到,如果分析方法固定式了延时,在延时短时间完成以前,没有响应,也会报错。

还有没有其它偏远地区可以固定式延时呢?正确是负责任的,Interceptor那时候我们也可以假设延时。比如说就是我们特指的两种所设的延时的分析方法,分别是直达维度和允诺分析方法维度。

clientConn, err := grpc.Dial(serverAddress, grpc.WithTimeout(5 * time.Second), grpc.WithInsecure())if err != nil { log.Println("Dial failed!") return err}c := pb.NewGreeterClient(conn)c.SayHello(context.Background(), &pb.HelloRequest{Name: "world"}, WithForcedTimeout(time.Duration(10)*time.Second))

那么上述所设是如何订立的?如何传递到多用户的呢?先看下

grpc.WithTimeout CVS位于google.golang.org/grpc@v1.50.1/dialoptions.go

func WithTimeout(d time.Duration) DialOption { return newFuncDialOption(func(o *dialOptions) { o.timeout = d })}

它变更了dialOptions的timeout

type dialOptions struct { timeout time.Duration}type DialOption interface { apply(*dialOptions)}

而dialOptions是ClientConn的一个表征

type ClientConn struct { dopts dialOptions }

我们发起人直达的时候用的就是这个表征上的timeout

func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *ClientConn, err error) { if cc.dopts.timeout> 0 { var cancel context.CancelFunc ctx, cancel = context.WithTimeout(ctx, cc.dopts.timeout) defer cancel() }}

Interceptor是如何让延时订立的呢,直觉更简单,我们看下它的假设,在发起人毫无疑问呼叫以前先呼叫Interceptor,这个时候所设延时短时间:

func TimeoutInterceptor(t time.Duration) grpc.UnaryClientInterceptor { return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { timeout := t if v, ok := getForcedTimeout(opts); ok { timeout = v } if timeout <= 0 { return invoker(ctx, method, req, reply, cc, opts...) } ctx, cancel := context.WithTimeout(ctx, timeout) defer cancel() return invoker(ctx, method, req, reply, cc, opts...) }}func getForcedTimeout(callOptions []grpc.CallOption) (time.Duration, bool) { for _, opt := range callOptions { if co, ok := opt.(TimeoutCallOption); ok { return co.forcedTimeout, true } } return 0, false}

而延时短时间是我们发起人呼叫的时候通过option传递留下来的

type TimeoutCallOption struct { grpc.EmptyCallOption forcedTimeout time.Duration}func WithForcedTimeout(forceTimeout time.Duration) TimeoutCallOption { return TimeoutCallOption{forcedTimeout: forceTimeout}}

认清会话的延时短时间是如何所设和订立的直至,多用户怎么保证,会话延时直至,马上重启当前任务呢?回答这个疑问以前,我们看下延时是如何传递的。首先,计算显现出来正确:grpc协议将延时短时间放有在HTTP header 允诺头;还有。会话所设的延时短时间为5秒,http2的header如下

grpc-timeout: 4995884u

其中u透露短时间单位为兆,4995884u 约莫 5秒。然后多用户接收到该允诺后,就可以根据这个短时间计算显现出有否延时,由header 延时所设。

那么header是何时由client所设的,以及何时由多用户判别的呢?

google.golang.org/grpc@v1.50.1/internal/transport/http2_client.go

发起人会话允诺的时候会呼叫

func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (*Stream, error) { headerFields, err := t.createHeaderFields(ctx, callHdr)

内部我们可以想到,它从context;还有取显现出延时累计短时间,然后写入header "grpc-timeout";还有

func (t *http2Client) createHeaderFields(ctx context.Context, callHdr *CallHdr) ([]hpack.HeaderField, error) { if dl, ok := ctx.Deadline(); ok { // Send out timeout regardless its value. The server can detect timeout context by itself. // TODO(mmukhi): Perhaps this field should be updated when actually writing out to the wire. timeout := time.Until(dl) headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-timeout", Value: grpcutil.EncodeDuration(timeout)}) }

判别的过程:

google.golang.org/grpc@v1.50.1/internal/transport/handler_server.go

func NewServerHandlerTransport(w http.ResponseWriter, r *http.Request, stats []stats.Handler) (ServerTransport, error) { if v := r.Header.Get("grpc-timeout"); v != "" { to, err := decodeTimeout(v) if err != nil { return nil, status.Errorf(codes.Internal, "malformed time-out: %v", err) } st.timeoutSet = true st.timeout = to } if timeoutSet { s.ctx, s.cancel = context.WithTimeout(t.ctx, timeout) } else { s.ctx, s.cancel = context.WithCancel(t.ctx) }

可以想到,首先从header;还有取显现出延时短时间,然后所设context.WithTimeout

func (ht *serverHandlerTransport) HandleStreams(startStream func(*Stream), traceCtx func(context.Context, string) context.Context) {if ht.timeoutSet {ctx, cancel = context.WithTimeout(ctx, ht.timeout)} else {ctx, cancel = context.WithCancel(ctx)}

google.golang.org/grpc@v1.50.1/internal/transport/http2_server.go

func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(*Stream), traceCtx func(context.Context, string) context.Context) (fatal bool) {case "grpc-timeout":timeoutSet = truevar err errorif timeout, err = decodeTimeout(hf.Value); err != nil {headerError = true}。

先诺欣
丁桂儿肚脐贴和肠炎宁哪个止泻效果好
来氟米特片能长期吃吗?类风湿患者要注意这几点!
英太青治牙疼吗
宝宝消化不良吃什么药效果好
标签:链接
友情链接: