现在网上大部分都是 grpc 相关的介绍,真正涉及到 grpc 的配置使用的文章还是比较少的
所以本系列着重介绍 grpc 开发时可以能会用到的一些配置
grpc 支持在 server 端和 client 端发送 metedata,一些验证信息之类的可以放在这个里边
可以通过 metadata 包来构建
type MD map[string][]string
一个键可以对应多个值
func New(m map[string]string) MD
func Pairs(kv ...string) MD
md := metadata.New(map[string]string{"key1": "val1", "key2": "val2"})
md = metadata.Pairs(
"key1", "val1",
"key1", "val1-2", // "key1" will have map value []string{"val1", "val1-2"}
"key2", "val2",
)
key 中大写字母会被转化为小写grpc-
开头的键为 grpc 内部使用,如果再 metadata 中设置这样的键可能会导致一些错误
metadata 中可以存储二进制数据
key 以 -bin 为后缀,这时,值会在传输前后以 base64 进行编解码
md := metadata.Pairs(
"key", "string value",
"key-bin", string([]byte{96, 102}),
)
服务端和客户端接收到的 metadata 如果被修改的话可能会导致 race
通过 Copy() 方法返回的 metadata 可以修改
func (md MD) Copy() MD
有两种发送 metadata 到 server 的方法
推荐的方法是使用 AppendToOutgoingContext
如果 metadata 已存在则会合并,不存在则添加
func AppendToOutgoingContext(ctx context.Context, kv ...string) context.Context
// create a new context with some metadata
ctx := metadata.AppendToOutgoingContext(ctx, "k1", "v1", "k1", "v2", "k2", "v3")
// later, add some more metadata to the context (e.g. in an interceptor)
ctx := metadata.AppendToOutgoingContext(ctx, "k3", "v4")
而 NewOutgoingContext
则会覆盖 context 中 已有的 metadata
func NewOutgoingContext(ctx context.Context, md MD) context.Context
// create a new context with some metadata
md := metadata.Pairs("k1", "v1", "k1", "v2", "k2", "v3")
ctx := metadata.NewOutgoingContext(context.Background(), md)
client 和 server 接收 metadata 的方式是不同的,metadata 会被分为 header
和 triler
unary RPC
可以在调用的时候,使用 CallOption Header 和 Trailer 来获取
```go
var header, trailer metadata.MD // variable to store header and trailer
r, err := client.SomeRPC(
ctx,
someRequest,
grpc.Header(&header), // will retrieve header
grpc.Trailer(&trailer), // will retrieve trailer
)
// do something with header and trailer
stream RPC
可以通过 ClientStream
接口的 Header, Trailer 方法来获取
stream, err := client.SomeStreamingRPC(ctx)
// retrieve header
header, err := stream.Header()
// retrieve trailer
trailer := stream.Trailer()
server 端会把 metadata 分为 header 和 trailer 发送给 client
unary RPC
可以通过 CallOption grpc.SendHeader 和 grpc.SetTriler 来发送 header
, trailer
metadata
SetTriler 可以被调用多次,并且所有 metadata 会被合并
当 RPC 返回的时候, trailer metadata 会被发送
func SendHeader(ctx context.Context, md metadata.MD) error
func SetTrailer(ctx context.Context, md metadata.MD) error
func (s *server) SomeRPC(ctx context.Context, in *pb.someRequest) (*pb.someResponse, error) {
// create and send header
header := metadata.Pairs("header-key", "val")
grpc.SendHeader(ctx, header)
// create and set trailer
trailer := metadata.Pairs("trailer-key", "val")
grpc.SetTrailer(ctx, trailer)
}
stream RPC 则可以直接使用 ServerStream 接口的方法
func (s *server) SomeStreamingRPC(stream pb.Service_SomeStreamingRPCServer) error {
// create and send header
header := metadata.Pairs("header-key", "val")
stream.SendHeader(header)
// create and set trailer
trailer := metadata.Pairs("trailer-key", "val")
stream.SetTrailer(trailer)
}
SendHeader 最多会被调用一次,提供的metadata会通过 SetHeader 来设置
SetHeader 可以被多次调用,所有的 metadata 都会被合并
当遇到以下行为的时候 metadata 会被发送
服务端调用 FromIncomingContext
即可从 context 中接收 client 发送的 metadata
func FromIncomingContext(ctx context.Context) (md MD, ok bool)
func (s *server) SomeRPC(ctx context.Context, in *pb.someRequest) (*pb.someResponse, error) {
md, ok := metadata.FromIncomingContext(ctx)
// do something with metadata
}
func (s *server) SomeStreamingRPC(stream pb.Service_SomeStreamingRPCServer) error {
md, ok := metadata.FromIncomingContext(stream.Context()) // get context from stream
// do something with metadata
}
example:metadata
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/DAGU131/article/details/105839187
内容来源于网络,如有侵权,请联系作者删除!