认识GO--gRPC的metadata
参考:
写给go开发者的gRPC教程-metadata-CSDN博客
https://blog.csdn.net/kevin_tech/article/details/129395177?ops_request_misc=%257B%2522request%255Fid%2522%253A%25221f2f2e26f48c755c33344ccb171a49fc%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=1f2f2e26f48c755c33344ccb171a49fc&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-129395177-null-null.142^v100^pc_search_result_base6&utm_term=go%E7%9A%84metadata&spm=1018.2226.3001.4187
什么是metadata?
元数据。他就是我们的对数据进行封装的一个单位化数据。在某些理解上,他是一个。他们是一个整体。这么说有点抽象,举例说明吧:目前我们有一个请求,请求的数据是:用户名+密码。这就是我们常说的”数据“。那么请求的方法是什么?编码是什么?token呢?cookie呢?他们提供了有关其他数据的信息,用于描述数据的特征、来源、用途、关系等诸多方面。因此,我们将他们也封装到一起,打包成我们的metadata,一起发送,一起接收......
那么在go语言中,metadata又是什么?具体的说,应该是在go的grpc中,请求和响应携带的“元数据”,他们就叫做 metadata。grpc基于http2.0,那么metadata在grpc的一次调用就是一个生命周期。
简单的理解:metadata是context中负责数据打包的载体,配合context实现服务端和客户端之间的互相传递信息。
metadata的创建
我们先了解一个东西:在grpc中,metadata的本质其实是一个map[string][]string。
New()
md := metadata.New(map[string]string{"key1":"value1","key2":"value2"})
Pairs()
要注意如果有相同的 key 会自动合并
md := metadata.Pairs(
"key1", "value1",
"key1", "value1.2",
"key2", "value2",
)
"key1" will have map value []string{"value1", "value1.2"}
Join()
md1 := metadata.Pairs("k1", "v1", "k2", "v2")
md2 := metadata.New(map[string]string{"key1":"value1","key2":"value2"})
md := metadata.Join(md1, md2)
合并md1和md2为md
存储二进制数据(-bin)
在 metadata 中,key 永远是 string 类型,但是 value 可以是 string 也可以是二进制数据。为了在 metadata 中存储二进制数据,我们仅仅需要在 key 的后面加上一个 - bin 后缀。具有 - bin 后缀的 key 所对应的 value 在创建 metadata 时会被编码(base64),收到的时候会被解码:
md := metadata.Pairs(
"key", "string value",
"key-bin", string([]byte{96, 102},
)
关于其他metadata的操作:https://pkg.go.dev/google.golang.org/grpc@v1.44.0/metadata
metadata的发送
由于,他是为了配合context传递上下文信息的,所以,metadata的传递可以是双向的。
Client----->Server
Client发送
覆盖式发送NewOutgoingContext
ctx := metadata.NewOutgoingContext(context.Background(), md)
追加式发送AppendToOutgoingContext
// 如果对应的 context 没有 metadata,那么就会创建一个
ctx := metadata.AppendToOutgoingContext(ctx, "k1", "v1", "k1", "v2", "k2", "v3")
// 如果已有 metadata 了,那么就将数据添加到原来的 metadata (例如在拦截器中)
ctx := metadata.AppendToOutgoingContext(ctx, "k3", "v4")
Server接收
使用FromIncomingContext
这里不管是普通调用还是流式调用,都是从contex.Context中读取metadata
核心的代码:
// 普通调用
md, ok := metadata.FromIncomingContext(ctx)
// 流式调用
md, ok := metadata.FromIncomingContext(stream.Context())
Server----->Client
服务端发送的metadata被分成了header和 trailer两者,因而客户端也可以读取两者。
trailer:服务端在处理完一个请求后,除了正常的响应消息主体外,可能还需要传递一些不能在响应头部(header)中发送的信息。这些信息可能是在处理请求过程中才生成的,或者因为某些协议规定、性能考虑等因素而适合放在消息结尾发送。
Server发送
对于普通RPC(unary RPC)server可以使用grpc包中提供的函数向client发送 header 和trailer
-
grpc.SendHeader() -
grpc.SetHeader() -
grpc.SetTrailer()
对于流式RPC(streaming RPC)server可以使用ServerStream[1]接口中定义的函数向client发送header和 trailer
-
ServerStream.SendHeader() -
ServerStream.SetHeader() -
ServerStream.SetTrailer()
其中:
sendHeader是立即发送
setHeader是追加设置header,自动合并到一个header中,等到合适的机会发送
setTrailer一般设置一次,防止信息设置混乱,因此也是 发送 tailer 信息
流式的差不多
Client接收
普通RPC使用grpc.Header()和grpc.Trailer()
流式RPC使用 ClientStream接口的返回对象调用
Header和Trailer区别
根本区别:发送的时机不同!
✨ headers会在下面三种场景下被发送
-
SendHeader()被调用时(包含grpc.SendHeader和stream.SendHeader) -
第一个响应被发送时
-
RPC结束时(包含成功或失败)
✨ trailer会在rpc返回的时候,即这个请求结束的时候被发送
差异在流式RPC(streaming RPC)中比较明显:
因为trailer是在服务端发送完请求之后才发送的,所以client获取trailer的时候需要在stream.CloseAndRecv或者stream.Recv 返回非nil错误 (包含 io.EOF)之后
如果stream.CloseAndRecv之前调用stream.Trailer()获取的是空
stream, err := client.SomeStreamingRPC(ctx)// retrieve header
header, err := stream.Header()// retrieve trailer
// `trailer`会在rpc返回的时候,即这个请求结束的时候被发送
// 因此此时调用`stream.Trailer()`获取的是空
trailer := stream.Trailer()stream.CloseAndRecv()// retrieve trailer
// `trailer`会在rpc返回的时候,即这个请求结束的时候被发送
// 因此此时调用`stream.Trailer()`才可以获取到值
trailer := stream.Trailer()
使用场景
当我们把metadata类比成HTTP Header的时候,那么metadata的使用场景也可以借鉴HTTP的Header。如传递用户token进行用户认证,传递trace进行链路追踪等
相关文章:
认识GO--gRPC的metadata
参考: 写给go开发者的gRPC教程-metadata-CSDN博客https://blog.csdn.net/kevin_tech/article/details/129395177?ops_request_misc%257B%2522request%255Fid%2522%253A%25221f2f2e26f48c755c33344ccb171a49fc%2522%252C%2522scm%2522%253A%252220140713.130102334…...
2024年安徽省职业院校技能大赛信息安全管理与评估
一、赛项名称 赛项名称:信息安全管理与评估 英文名称:Information Security Management and Evaluation 赛项组别:高职组 赛项归属:电子信息大类 二、竞赛目标 通过赛项检验参赛选手熟悉信息安全行业标准规范和信息 安全测试员新职…...
Perl 引用
Perl 引用 Perl,作为一种灵活而强大的编程语言,广泛用于系统管理、网络编程、GUI开发等领域。在Perl编程中,引用(References)是一个核心概念,它允许变量引用其他数据,从而创建复杂的数据结构&a…...
RT-Thread启动过程 :从汇编开始的启动流程
这个系列参考了《嵌入式实时操作系统RT-Thread设计与实现》,会详细介绍RT-Thread的启动流程,即是如何从零开始在开发板上运行起一个RTOS内核的。本文将会以 ch32v307VCT6 开发板为例展开进行详细介绍。主要包括:startup.S、初始化与系统相关的…...
Scala—“==“和“equals“用法(附与Java对比)
Scala 字符串比较—""和"equals"用法 Scala 的 在 Scala 中, 是一个方法调用,实际上等价于调用 equals 方法。不仅适用于字符串,还可以用于任何类型,并且自动处理 null。 Demo: Java 的 在 J…...
$route和$router的区别
在 Vue.js 中,$route 和 $router 都是 Vue Router 提供的对象,但它们有不同的用途和功能。 1. $router $router 是 Vue Router 实例的引用,它允许你通过 JavaScript 进行路由的控制和导航。你可以通过 $router 来执行路由的操作,…...
[工具升级问题] 钉钉(linux版)升级带来的小麻烦
本文由Markdown语法编辑器编辑完成。 1. 背景: 今日钉钉又发布了新的升级版本。由于我工作时使用的是Ubuntu 20.04版本,收到的升级推送信息是,可以升级到最新的7.6.25-Release版本。根据钉钉官方给出的历次更新版说明,这个新的版本…...
Leetcode经典题13--接雨水
题目描述 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。 输入输出示例 输入:height [0,1,0,2,1,0,1,3,2,1,2,1] 输出:6 解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1…...
yarn修改缓存位置
查看缓存位置 以下三个命令分别为:bin是yarn存储命令的二进制文件,global存储全局node_modules ,cache存储用下下载缓存,查看本机目前的目录: 查看bin目录命令:yarn global bin 查看global目录命令&…...
OpenHarmony-3.HDF input子系统(5)
HDF input 子系统OpenHarmony-4.0-Release 1.Input 概述 输入设备是用户与计算机系统进行人机交互的主要装置之一,是用户与计算机或者其他设备通信的桥梁。常见的输入设备有键盘、鼠标、游戏杆、触摸屏等。本文档将介绍基于 HDF_Input 模型的触摸屏器件 IC 为 GT91…...
RabbitMQ 消息持久化/镜像队列/lazy对时延影响
测试背景: 不同条件下RabbitMQ不同队列类型的生产时延测试: 测试环境: 机型:rabbimtq.2u4g.cluster 背景流量:1000 TPS 测试条件: 消息大小 4k,消息条数为1000条,时延取值为平均…...
【深度学习】深刻理解Swin Transformer
Swin Transformer 是一种基于 Transformer 的视觉模型,由 Microsoft 研究团队提出,旨在解决传统 Transformer 模型在计算机视觉任务中的高计算复杂度问题。其全称是 Shifted Window Transformer,通过引入分层架构和滑动窗口机制,S…...
[2015~2024]SmartMediaKit音视频直播技术演进之路
技术背景 2015年,因应急指挥项目需求,我们实现了RTMP推送音视频采集推送(采集摄像头和麦克风数据)模块,在我们做好了RTMP推送模块后,苦于没有一个满足我们毫秒级延迟诉求的RTMP播放器,于是第一…...
redis 使用Lettuce 当redis挂掉重启之后 网络是怎么重新连接
Lettuce是一个高性能的Java Redis客户端,支持同步、异步和反应式编程模式 Lettuce的核心功能包括: 高性能:通过使用Netty作为底层网络通信框架,实现了非阻塞IO,提高了性能。丰富的API:提供了丰富…...
【IntelliJ IDEA 集成工具】TalkX - AI编程助手
前言 在数字化时代,技术的迅猛发展给软件开发者带来了更多的挑战和机遇。为了提高技术开发群体在繁多项目中的编码效率和质量,他们需要一个强大而专业的工具来辅助开发过程,而正是为了满足这一需求,TalkX 应运而生。 一、概述 1…...
二叉搜索树Ⅲ【东北大学oj数据结构8-3】C++
二叉搜索树 III B:在二叉搜索树II中加入delete指令,创建程序对二叉搜索树T执行如下指令。 插入 k:将key k 插入到 T 中。 find k:报告T中是否存在key k。 delete k:删除key为 k 的节点。 打印:使用中序树遍…...
【面试笔记】CPU 缓存机制
CPU 缓存机制 1. CPU Cache 与 MMU1.1 MMU 是什么?TLB 又是什么?他们是怎么工作的?2.2 简述 Cache 与 MMU 的协作关系?2.3 简述 Cache 与 MMU 的协作工作流程? 2. CPU 多层次缓存2.1 什么是 CPU 的多层次缓存结构&…...
MySQL基础函数使用
目录 简介 1. 单行函数 1.1 字符串函数 1.2 日期函数 1.3 数值函数 1.4 转换函数 1.5 其他函数 2. 多行函数 示例: 3. 数据分组 示例: 4. DQL单表关键字执行顺序 示例: 5. 多表查询 示例: 6. 表与表的外连接 示例…...
解决docker环境下aspose-words转换word成pdf后乱码问题
描述 环境:docker 部署工具:Jenkins 需求:本地上传的word文档需要转换成pdf 问题:转换之后的pdf文档出现小框框(乱码) 转换成PDF的操作 pom: <dependency><groupId>org.apach…...
C# 生成随机数的方法
C# 提供了一种强大而方便的工具类 Random ,用于生成随机数。这里将分类讨论如何通过 C# 实现随机数生成,以及应用于实际情况中的一些具体方案。 一、Random 类概述 Random 类表示一个伪随机数生成器,用于生成满足随机性统计要求的数字序列。…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...
STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...
视频字幕质量评估的大规模细粒度基准
大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...
sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...
JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...
保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...
20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
Java求职者面试指南:计算机基础与源码原理深度解析
Java求职者面试指南:计算机基础与源码原理深度解析 第一轮提问:基础概念问题 1. 请解释什么是进程和线程的区别? 面试官:进程是程序的一次执行过程,是系统进行资源分配和调度的基本单位;而线程是进程中的…...
Caliper 负载(Workload)详细解析
Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...
Vite中定义@软链接
在webpack中可以直接通过符号表示src路径,但是vite中默认不可以。 如何实现: vite中提供了resolve.alias:通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...
