首页 > 其他分享 >gRPC高级——Metadata机制

gRPC高级——Metadata机制

时间:2024-07-13 20:27:46浏览次数:15  
标签:string err proto gRPC 高级 go Metadata metadata

什么是Metadata

gRPC让我们可以像本地调用一样实现远程调用,对于每一次的RPC调用中都可能会有一些有用的数据,而这些数据就可以通过metadata来传递。metadata是以key-value的形式存储数据的,其中key是string类型,而value是[]string,即一个字符串数组类型。metadata使得client和server能够为对方提供关于本次调用的一些信息,就像一次http请求的RequestHeaderResponseHeader一样。http中header的生命周周期是一次http请求,那么 metadata的生命周期就是一次RPC调用。

Metadata的结构

Metadata是由键值对组成的,每个键名都是字符串,值可以是字符串或二进制数据。为了兼容性和标准化,键名通常使用小写字母和连字符,避免使用大写字母。

Metadata的使用场景

  1. 身份验证
    • 传递访问令牌(如JWT、OAuth令牌)或API密钥进行身份验证。
    • 在每个请求中包含身份验证信息,以便服务器进行认证和授权。
  2. 追踪和日志
    • 传递追踪ID、请求ID或会话ID,用于分布式系统中的请求跟踪。
    • 方便在复杂的微服务架构中跟踪和调试请求链路。
  3. 自定义指令
    • 传递压缩指令,指示服务器使用特定的压缩算法返回数据。
    • 传递自定义头信息,以实现特定业务逻辑需求。

Go中的Metadata

源码:源码

文档:文档

1. 新建Metadata

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

// MD is a mapping from metadata keys to values. Users should use the following
// two convenience functions New and Pairs to generate MD.
type MD map[string][]string

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

// 方式一,使用metadata.New()
md := metadata.New(map[string]string{"key1": "value1", "key2": "value2"})

// 方式二:使用metadata.Pairs()
md := metadata.Pairs(
    "key1": "value1",
    "key1": "value1-2", // "key1" will have map value []string{"value1", "value1-2"}
    "key2": "value2"
)
2. 发送Metadata
md := metadata.Pairs("key","value")

//新建一个有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, error) {
    md,ok := metadata.FromIncomingContext(ctx)
	//do something with metadata
}

GO使用gRPC Metadata

0. 目录树如下
.
├── client
│   └── client.go
├── proto
│   ├── meta_grpc.pb.go
│   ├── meta.pb.go
│   └── meta.proto
└── server
    └── server.go

1. 建立proto/meta.proto文件
syntax = "proto3";

option go_package = ".;proto";

import "google/protobuf/empty.proto";

service GetMeta {
  rpc GetMeta(google.protobuf.Empty) returns (google.protobuf.Empty);
}

利用命令生成对应的go文件

cd proto/
protoc meta.proto --go_out=. --go-grpc_out=.
2. 建立server/server.go文件
package main

import (
	"context"
	"fmt"
	"net"

	"github.com/golang/protobuf/ptypes/empty"
	"google.golang.org/grpc"
	"google.golang.org/grpc/metadata"

	"go-try/metadata/proto"
)

type MetaServer struct {
	proto.UnimplementedGetMetaServer
}

func (s *MetaServer) GetMeta(ctx context.Context, empty2 *empty.Empty) (*empty.Empty, error) {
	md, ok := metadata.FromIncomingContext(ctx)
	if !ok {
		fmt.Println("get metadata err")
	}
	if tokenSlice, ok := md["token"]; ok {
		fmt.Println("token: ", tokenSlice[0])
	}
	return nil, nil
}

func main() {
	server := grpc.NewServer()
	proto.RegisterGetMetaServer(server, &MetaServer{})
	listen, err := net.Listen("tcp", "0.0.0.0:8080")
	if err != nil {
		panic("faild to listen : " + err.Error())
	}
	err = server.Serve(listen)
	if err != nil {
		panic("faild to start grpc : " + err.Error())
	}
}

3. 建立client/client.go文件
package main

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

	"github.com/golang/protobuf/ptypes/empty"
	"google.golang.org/grpc"

	"go-try/metadata/proto"
)

func main() {
	conn, err := grpc.NewClient("0.0.0.0:8080", grpc.WithInsecure())
	if err != nil {
		panic(err)
	}
	defer conn.Close()

	md := metadata.Pairs("token", "xxxxxxxxxxxxxxxxxxx")
	//md := metadata.New(map[string]string{
	//	"token": "xxxxxxxxxxxxxxxxxxx",
	//})
	ctx := metadata.NewOutgoingContext(context.Background(), md)

	cli := proto.NewGetMetaClient(conn)
	if _, err := cli.GetMeta(ctx, &empty.Empty{}); err != nil {
		panic(err)
	}
}

4. 分别运行server.go和client.go

运行结果如下:

token:  xxxxxxxxxxxxxxxxxxx

总结

通过Metadata机制,可以在不改变接口定义的情况下传递额外的信息,增强服务的灵活性和功能性。在实际应用中,根据具体需求合理设计和使用Metadata,可以实现高效、安全的gRPC通信。

标签:string,err,proto,gRPC,高级,go,Metadata,metadata
From: https://blog.csdn.net/MPY_3/article/details/140405776

相关文章

  • gRPC 高级——Interceptor 拦截器
    gRPC拦截器是一种用于在RPC方法调用的生命周期中拦截和处理请求和响应的机制。拦截器允许开发者在请求到达实际服务方法之前或在响应返回客户端之前执行自定义逻辑。它们类似于中间件,广泛应用于日志记录、身份验证、请求修改等场景。拦截器的种类客户端拦截器(ClientInter......
  • 福昕高级PDF编辑器专业版2024.2.0安装教程
    1、下载安装包2、双击安装程序进行安装3、修改安装位置,点击安装4、等待安装5安装完成,一定不能立即启用不要点击立即启用6、将patch的应用程序放到安装目录下面,双击启动7、点击应用8、执行完成,打开软件就可以用了如遇到福昕高级PDF编辑器失败,提示:本机已安装......
  • C# Newtonsoft.Json 高级用法
    一、基本用法Json.Net是支持序列化和反序列化DataTable,DataSet,EntityFramework和Entity的。下面分别举例说明序列化和反序列化。//序列化DataTableDataTabledt=newDataTable();dt.Columns.Add("Age",Type.GetType("System.Int32"));dt.Columns.Add("Name",Type.Get......
  • 实现一个 AI 聊天输入框:从基础到高级的指南
    引言随着人工智能和自然语言处理(NLP)技术的快速发展,基于AI的聊天系统变得越来越普遍。无论是简单的问答系统还是复杂的客服聊天机器人,聊天输入框都是用户与系统交互的关键组件。本文将详细介绍如何实现一个功能丰富的AI聊天输入框,从基础组件到高级功能,包括用户输入处理、界......
  • ISIS 高级特性
    1ISIS快速收敛为了提高路由的收敛速度而作的扩展特性,包括:I-SPF(IncrementalSPF,增量最短路径优先算法)、PRC、智能定时器、LSP快速扩散。同时也支持故障恢复快速收敛,例如通过IS-ISAutoFRR实现备份链路的快速切换,也可以与BFD联动实现对故障的快速感知。1.1I-SPF当网络拓扑......
  • protobuf-net.Grpc 笔记
    众所周知,Grpc很好用,但每次都需要手动编写*.proto文件,protobuf-net.Grpc个人感觉最大的优势是不用写*.proto文件,相关教程如下:https://learn.microsoft.com/zh-cn/aspnet/core/grpc/code-first?view=aspnetcore-8.0https://protobuf-net.github.io/protobuf-net.Grpc/gettingst......
  • 研究gRPC所给的helloworld例子
    这里我以编写一个远程过程调用,客户端传过来请求,远程过程调用就可以返回当前时间。(daytime服务器熟知端口是13,这里并不是搭建daytime,只是为了测试远程过程调用是否成功)CMakeLists.txt文件的编写cmake_minimum_required(VERSION3.8)project(HelloWorldCCXX)include(../cmake/......
  • 在C++中使用gRPC框架
    概览在gRPC里客户端应用可以像调用本地对象一样直接调用另一台不同机器上的服务端应用的方法,使得您能够更容易地创建分布式应用和服务。与许多RPC系统类似,gRPC也是基于以下理念:定义一个服务,指定其能够被远程调用的方法(包括参数和返回类型)。在服务器端实现这个接口,并运行一个gRPC......
  • 高级java每日一道面试题-2024年7月12日
    如果有遗漏,评论区告诉我进行补充面试官问:你对IO流了解多少我回答:一.什么是JavaIO流?回答:JavaIO流是用于处理输入和输出操作的一组类和接口。它允许程序从不同的数据源(如文件、网络连接、内存缓冲区等)读取数据或将数据写入到不同的目标位置。IO流分为字节流和......
  • 王牌站士Ⅱ--针对 LLM/SLM 的高级 RAG
    前言检索增强生成(RAG)已成为一种增强语言模型能力的强大技术。通过检索和调整外部知识,RAG可让模型生成更准确、更相关、更全面的文本。RAG架构主要有三种类型:简单型、模块化和高级RAG:NaiveRAG采用GPT-3这样的单片模型,并简单地根据检索到的证据段落对其进行条件化......