golang grpc中metadata的使用

本文深入探讨了gRPC中的Metadata概念,它允许在RPC调用中传递额外信息。介绍了在Go中如何创建、发送和接收Metadata,以及在gRPC服务端和客户端的应用示例。通过Metadata,可以在RPC调用的生命周期内传递如身份验证信息等关键数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

gRPC让我们可以像本地调用一样实现远程调用,对于每一次的RPC调用中,都可能会有一些在header中传递的数据,而这些数据就可以通过metadata来传递。

metadata是以key-value的形式存储数据的,其中key是string类型,value是[]string类型,即一个字符串切片类型。metadata使得client和server能够为对方提供关于本次调用的一些信息,就像一次http请求的RequestHeader和ResponseHeader一样。http中header的生命周期是一次http请求,那么metadata的生命周期就是一次RPC调用。

1. go中使用metadata

项目源代码路径:https://github.com/grpc/grpc-go/tree/master/metadata

项目文档:https://github.com/grpc/grpc-go/blob/master/Documentation/grpc-metadata.md

 使用的go包:"google.golang.org/grpc/metadata"

1)新建metadata

MD 类型实际上是map,key是string,value是string类型的slice。

type MD map[string][]string

创建的时候可以像创建普通的map类型一样使用new关键字进行创建:

//第一种方式
md := metadata.New(map[string]string{"key1": "val1", "key2": "val2"})

//第二种方式 key不区分大小写,会被统一转成小写
md := metadata.Pairs(
    "key1", "val1",
    "key1", "val1-2", // "key1" will have map value []string{"val1", "val1-2"}
    "key2", "val2",
)

2)发送metadata

md := metadata.Pairs("key", "val")

// 新建一个有 metadata 的 context
ctx := metadata.NewOutgoingContext(context.Background(), md)

// 单向 RPC
response, err := client.SomeRPC(ctx, someRequest)

3)接收metadata

func (s *server) SomeRPC(ctx context.Context, in *pb.SomeRequest) (*pb.SomeResponse, err) {
    md, ok := metadata.FromIncomingContext(ctx)
    // do something with metadata
}

2.gRPC中使用metadata

1)proto

syntax = "proto3";
option go_package = "./;proto";

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

执行命令编译文件,生成.pb.go文件:protoc -I . test.proto --go_out=plugins=grpc:.

2)client 

package main

import (
	"context"
	"fmt"
	"go-class/rpc/07metadata/proto"
	"google.golang.org/grpc"
	"google.golang.org/grpc/metadata"
)

func main() {
	conn, err := grpc.Dial(":8083", grpc.WithInsecure())
	if err != nil {
		panic(err)
	}
	defer conn.Close()
	c := proto.NewGreeterClient(conn)

	//写入metadata***********
	md := metadata.New(map[string]string{
		"name": "lff",
		"password": "123456",
	})
	ctx := metadata.NewOutgoingContext(context.Background(), md)
	r, err := c.SayHello(ctx, &proto.HelloRequest{Name: "lff111"})
	if err != nil {
		panic(err)
	}
	fmt.Println(r.Message)
}

3)server

package main

import (
	"context"
	"fmt"
	"net"

	"google.golang.org/grpc"
	"google.golang.org/grpc/metadata"

	"go-class/rpc/07metadata/proto"
)

type Server struct {}

func (s *Server) SayHello(ctx context.Context, req *proto.HelloRequest) (*proto.HelloReply, error) {
    //获取header*********
	md, ok := metadata.FromIncomingContext(ctx)
	if ok {
		fmt.Println("get metadata error")
	}
	for key, val := range md {
		fmt.Println(key, val)
	}
    //获取header中的name*********
	//if nameSlice, ok := md["name"]; ok {
	//	fmt.Println(nameSlice)
	//	for i, e := range nameSlice {
	//		fmt.Println(i, e)
	//	}
	//}
	return &proto.HelloReply{
		Message: "Hello " + req.Name,
	}, nil
}

func main(){
	g := grpc.NewServer()
	proto.RegisterGreeterServer(g, &Server{})
	lis, err := net.Listen("tcp", "127.0.0.1:8083")
	if err != nil {
		panic("failed to listen:" + err.Error())
	}
	err = g.Serve(lis)
	if err != nil {
		panic("failed to start grpc:" + err.Error())
	}
}

先启动server,在启动client端,结果看到打印出的header

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值