认识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 类表示一个伪随机数生成器,用于生成满足随机性统计要求的数字序列。…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...
label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...
Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...
转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...
自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...
tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...
