gRPC 使用Context在服务间传递内容

2,330 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

使用Context来进行超时控制的文章很多,但是没有说怎么传递自定义的内容。

主要使用的是gprc里面的metadata

github.com/grpc/grpc-g…

单次调用

客户端

通过metadata的NewOutgoingContext方法生成个context,调用的时候传入

import (
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
)

conn, err := grpc.Dial("127.0.0.1:50005", grpc.WithInsecure())
if err != nil {
  log.Fatalf("can not connect with server %v", err)
}

client := pb.NewMathClient(conn)

header := metadata.New(map[string]string{"authorization": "this is nick", "space": "", "org": "", "limit": "", "offset": ""})
ctx := metadata.NewOutgoingContext(context.Background(), header)

test, err := client.Test(ctx, &pb.Request{
  Num: 0,
})

服务端

接收用FromIncomingContext

func (s server) Test(ctx context.Context, in *pb.Request) (*pb.Response, error) {
   md, _ := metadata.FromIncomingContext(ctx)
   fmt.Printf("Test md %v \n", md)
   return &pb.Response{Result: 1}, nil
}

可以这样来用:

if ok {
    values = md.Get("authorization")
}
if len(values) > 0 {
    token = values[0]
}

流式调用

双向流式参考:github.com/pahanini/go…

客户端

一样的 只不过是在创建流的时候传入

conn, err := grpc.Dial("127.0.0.1:50005", grpc.WithInsecure())
if err != nil {
   log.Fatalf("can not connect with server %v", err)
}


header := metadata.New(map[string]string{"authorization": "this is nick", "space": "", "org": "", "limit": "", "offset": ""})
cctx := metadata.NewOutgoingContext(context.Background(), header)
// create stream
client := pb.NewMathClient(conn)

stream, err := client.Max(cctx)
if err != nil {
   log.Fatalf("openn stream error %v", err)

stackoverflow.com/questions/4… Note that for a stream there are only three times that headers can be sent: in the context used to open the initial stream, via grpc.SendHeader, and grpc.SetTrailer. It is not possible to set headers on arbitrary messages in a stream. For an unary RPC header are sent with every message and can be set in the initial context, with grpc.SendHeader and grpc.SetHeader, and grpc.SetTrailer.

SetHeader SendHeader

pkg.go.dev/google.gola…