云原生【免费下载链接】kubevirtKubernetes Virtualization API and runtime in order to define and manage virtual machines.项目地址https://gitcode.com/gh_mirrors/ku/kubevirt点击查看免费下载本文以 KubeVirt 仓库中 vendored 的 fxamacker/cbor v2 文档为骨架系统讲解 CBORRFC 8949编解码库的核心能力、API 用法、安全配置与工程实践。读完本文你将掌握如何用 Go 语言对 CBOR 与 CBOR Sequences 进行编解码、通过 Struct Tag 压缩编码体积、使用预设与自定义模式、扩展 CBOR Tags并了解该库在 KubeVirt 依赖树中的落地形态。一、认识 CBOR 与 fxamacker/cborCBORConcise Binary Object Representation是 IETF STD 94RFC 8949定义的二进制数据格式被设计为 JSON、MessagePack、Protocol Buffers 等格式的可信替代方案适合长期稳定的协议与存储场景。fxamacker/cbor是 Go 语言中与该标准完全一致的 CBOR 编解码库同时支持CBOR SequencesRFC 8742多个编码后的 CBOR 数据项首尾拼接而成Extended Diagnostic Notation / EDNRFC 8610 Appendix G将 CBOR 数据翻译为可读文本Diagnose/DiagnoseFirstCBOR Tags内置与用户自定义标签均受支持Core Deterministic EncodingRFC 8949 核心确定性编码与重复 map 键检测等特性。该库的 API 与encoding/json高度一致Marshal、Unmarshal、NewEncoder、NewDecoder等签名相同并额外提供简化并发与选项配置的接口。设计目标是在安全、速度、并发、编码体积、易用性之间做工程权衡。在 KubeVirt 仓库中的位置在 KubeVirt 仓库中fxamacker/cbor以v2.9.0版本、// indirect间接依赖的形式进入依赖树见 go.mod 以及 staging/src/kubevirt.io/api/go.mod、staging/src/kubevirt.io/client-go/go.mod 中的同版本记录。其完整源码被 vendored 在 vendor/github.com/fxamacker/cbor/v2/ 目录下并通过 BUILD.bazel 接入 Bazel 构建体系。从源码结构看它主要由 encode.go、decode.go、stream.go、tag.go、valid.go、diagnose.go 等模块构成为依赖树中上游组件如 Kubernetes 生态对 COSE/WebAuthn 等 CBOR 数据项的处理提供底层编解码能力。二、核心特性总览速度编码与解码不使用 Go 的unsafe包速度快较慢的设置均为可选开启opt-in。默认限制允许以极快的速度、极低的内存开销拒绝畸形 CBOR 数据。安全解码器提供可配置的限制以防御恶意输入并支持重复 map 键检测。库在 2022 年通过了多次保密安全评估NCC Group 为 Microsoft Corporation 准备的非保密安全评估针对 go-cose 中该库子集中未发现漏洞。对比而言Go 标准库encoding/gob并非为对抗恶意输入而设计详见其包文档 Security 一节。数据体积Struct tag 选项toarray、keyasint、omitempty、omitzero与字段 tag-会自动缩小结构体的编码尺寸编码时还可选择性地在数值可容纳时把 float64 压缩为 float32 乃至 float16。易用性API 与encoding/json大体一致并提供简化并发的接口编码/解码模式可在启动时创建一次之后由任意 goroutine 安全复用。内置 Core Deterministic Encoding、Preferred Serialization、CTAP2 Canonical CBOR 等预设。可扩展性支持 CBOR 扩展点如 CBOR Tags与大量设置项API 提供接口允许用户自定义编码与解码行为而无需修改库本身。三、安全的可配置解码解码器内置可配置限制用于防御恶意 CBOR 数据并且在拒绝畸形数据上非常快。README 中给出的恶意数据拒绝基准输入为 10 字节恶意 CBOR 数据、解码到[]byteCodecSpeed (ns/op)MemoryAllocsfxamacker/cbor 2.7.047 ± 7%32 B/op2 allocs/opugorji/go 1.2.125878187 ± 3%67111556 B/op13 allocs/op基准环境go1.22.7 / linux/amd64 / i5-13600Kgo test -bench. -benchmem -count20更快的硬件可缩小差距。相比之下部分其他 codec 在解码坏数据时可能崩溃或消耗过多资源。README 特别警告encoding/gob解码 181 字节数据即可触发fatal error: runtime: out of memory其包文档也明确说明未针对对抗性输入加固。四、用 Struct Tag 选项压缩编码体积Struct tag 可自动缩小结构体编码尺寸并提升速度支持的选项toarray不带字段名编码解码时仍能还原回原结构体keyasint将字段名编码为整数解码时还原omitempty编码时省略空字段omitzero编码时省略零值字段。特殊规则结构体字段 tag-表示编码时省略该字段且当结构体使用toarray时编码器会忽略omitempty与omitzero以避免编码数组元素位置变化从而保证解码时能将元素精确对应回 Go 结构体字段。这些选项的实现细节可参考 structfields.goomitzero还按 Go 版本拆分为 omitzero_go124.go 与 omitzero_pre_go124.go 两个实现。示例字段 tag - 的用法package main import ( encoding/json fmt github.com/fxamacker/cbor/v2 ) // 标签 cbor:- 使 Type 字段在编码为 CBOR 时被省略。 type Entity struct { _ struct{} cbor:,toarray ID uint64 json:id Type string cbor:- json:typeOf Name string json:name } func main() { entity : Entity{ ID: 1, Type: int64, Name: Identifier, } c, _ : cbor.Marshal(entity) diag, _ : cbor.Diagnose(c) fmt.Printf(CBOR in hex: %x\n, c) fmt.Printf(CBOR in edn: %s\n, diag) j, _ : json.Marshal(entity) fmt.Printf(JSON: %s\n, string(j)) fmt.Printf(JSON encoding is %d bytes\n, len(j)) fmt.Printf(CBOR encoding is %d bytes\n, len(c)) // 输出 // CBOR in hex: 82016a4964656e746966696572 // CBOR in edn: [1, Identifier] // JSON: {id:1,typeOf:int64,name:Identifier} // JSON encoding is 45 bytes // CBOR encoding is 13 bytes }示例三层嵌套结构体编码为 1 字节 CBORpackage main import ( encoding/hex encoding/json fmt github.com/fxamacker/cbor/v2 ) type GrandChild struct { Quux int json:,omitempty } type Child struct { Baz int json:,omitempty Qux GrandChild json:,omitempty } type Parent struct { Foo Child json:,omitempty Bar int json:,omitempty } func cb() { results, _ : cbor.Marshal(Parent{}) fmt.Println(hex(CBOR): hex.EncodeToString(results)) text, _ : cbor.Diagnose(results) // Diagnostic Notation fmt.Println(DN: text) } func js() { results, _ : json.Marshal(Parent{}) fmt.Println(hex(JSON): hex.EncodeToString(results)) text : string(results) // JSON fmt.Println(JSON: text) } func main() { cb() fmt.Println(-------------) js() }输出DN 为 Diagnostic Notationhex(CBOR): a0 DN: {} ------------- hex(JSON): 7b22466f6f223a7b22517578223a7b7d7d7d JSON: {Foo:{Qux:{}}}即 JSON 编码为 18 字节而 CBOR 仅 1 字节。Struct tag 选项尤其简化了要求 CBOR 数组或整数键 map 的基于 CBOR 的协议如 COSE、CWT的实现。五、快速上手安装与默认模式安装go get github.com/fxamacker/cbor/v2随后import github.com/fxamacker/cbor/v2。关键概念CBOR 数据项单块 CBOR 数据其结构可包含 0 个或多个嵌套数据项CBOR 序列0 个或多个编码后 CBOR 数据项的拼接。包级函数只使用默认设置构成默认模式// API 与 encoding/json 的 Marshal、Unmarshal、Encode、Decode 等一致。 b, err cbor.Marshal(v) // 将 v 编码为 []byte b err cbor.Unmarshal(b, v) // 将 []byte b 解码到 v decoder cbor.NewDecoder(r) // 用 io.Reader r 创建解码器 err decoder.Decode(v) // 解码一个 CBOR 数据项到 v // v2.7.0 新增 MarshalToBuffer() 与 UserBufferEncMode 接口。 err cbor.MarshalToBuffer(v, b) // 将 v 编码到 b而非使用内置 buf pool // v2.5.0 新增返回剩余字节的函数。 // UnmarshalFirst 解码第一个 CBOR 数据项并返回剩余字节。 rest, err cbor.UnmarshalFirst(b, v) // DiagnoseFirst 将第一个 CBOR 数据项翻译为文本并返回剩余字节。 text, rest, err cbor.DiagnoseFirst(b) // 注意若存在剩余字节Unmarshal() 返回 ExtraneousDataError // 而 UnmarshalFirst() 与 DiagnoseFirst() 允许尾部字节。重要提示CBOR 设置允许在速度、安全、编码体积等之间权衡——不同 CBOR 库的默认设置可能不同而基于 CBOR 的格式或协议通常要求特定设置。例如 WebAuthn 使用CTAP2 Canonical CBOR该库直接提供预设。六、预设与自定义模式预设Presets// EncOptions 是编码器设置的结构体。 func CoreDetEncOptions() EncOptions // RFC 8949 Core Deterministic Encoding func PreferredUnsortedEncOptions() EncOptions // RFC 8949 Preferred Serialization func CanonicalEncOptions() EncOptions // RFC 7049 Canonical CBOR func CTAP2EncOptions() EncOptions // FIDO2 CTAP2 Canonical CBOR预设可直接使用也可作为自定义设置的起点。自定义模式模式Mode由设置创建创建后设置不可变。建议在启动时创建并复用它安全支持并发使用// 创建编码模式。 opts : cbor.CoreDetEncOptions() // 以预设选项为起点 opts.Time cbor.TimeUnix // 按需修改任意设置 em, err : opts.EncMode() // 创建不可变编码模式 // 复用该编码模式并发安全。 // API 与 encoding/json 一致。 b, err : em.Marshal(v) // 将 v 编码为 []byte b encoder : em.NewEncoder(w) // 用 io.Writer w 创建编码器 err : encoder.Encode(v) // 将 v 编码到 io.Writer w默认模式与自定义模式都会自动应用 Struct tag。底层实现中模式EncMode/DecMode由 EncOptions/DecOptions 结构体生成、持有不可变选项以避免副作用相关接口定义与文档可参考 doc.go 与 encode.go。用户指定缓冲区编码v2.7.0 起UserBufferEncMode接口扩展了EncMode新增MarshalToBuffer()接受用户指定缓冲区而非使用内置缓冲区池em, err : myEncOptions.UserBufferEncMode() // 创建 UserBufferEncMode 模式 var buf bytes.Buffer err em.MarshalToBuffer(v, buf) // 将 v 编码到提供的 buf七、CBOR Tags 扩展CBOR 标签通过TagSet指定可用自定义模式关联 TagSet 来处理em, err : opts.EncMode() // 无 CBOR tags em, err : opts.EncModeWithTags(ts) // 不可变 CBOR tags em, err : opts.EncModeWithSharedTags(ts) // 可变共享 CBOR tagsTagSet及使用它的模式均安全支持并发DecMode也有等价 API。使用 TagSet 与 TagOptions 的示例// 创建 TagSet并发安全。 tags : cbor.NewTagSet() // 将 COSE_Sign1 标签 18 注册到 signedCWT 类型。 tags.Add( cbor.TagOptions{EncTag: cbor.EncTagRequired, DecTag: cbor.DecTagRequired}, reflect.TypeOf(signedCWT{}), 18) // 创建带不可变 tags 的 DecMode。 dm, _ : cbor.DecOptions{}.DecModeWithTags(tags) // 带 tag 支持地 Unmarshal 到 signedCWT。 var v signedCWT if err : dm.Unmarshal(data, v); err ! nil { return err } // 创建带不可变 tags 的 EncMode。 em, _ : cbor.EncOptions{}.EncModeWithTags(tags) // 带 tag 编号地 Marshal signedCWT。 if data, err : em.Marshal(v); err ! nil { return err }fxamacker/cbor允许用户应用通过实现cbor.Marshaler与cbor.Unmarshaler接口来使用几乎任意当前或未来的 CBOR tag 编号。本质上用户应用实现MarshalCBOR与UnmarshalCBOR函数后会被该 codec 的Marshal、Unmarshal等自动调用。接口与Tag类型定义可参考 tag.go。示例Embedded JSON Tag for CBORtag 262RFC 8949 未提及 tag 262它是 IANA 分配的Embedded JSON Object标签可作用于字节串major type 2表示该字节串是一个 JSON 对象。完整实现如下package cbor_test import ( bytes encoding/json fmt github.com/fxamacker/cbor/v2 ) // cborTagNumForEmbeddedJSON 是 CBOR tag 编号 262。 const cborTagNumForEmbeddedJSON 262 // EmbeddedJSON 表示编码为带 tag 262 的 CBOR 数据项的 Go 值 // tag 内容是内嵌为 CBOR 字节串major type 2的 JSON 对象。 type EmbeddedJSON struct { any } func NewEmbeddedJSON(val any) EmbeddedJSON { return EmbeddedJSON{val} } // MarshalCBOR 将 EmbeddedJSON 编码为带 tag 262 的 CBOR 数据项。 func (v EmbeddedJSON) MarshalCBOR() ([]byte, error) { data, err : json.Marshal(v) if err ! nil { return nil, err } tag : cbor.Tag{ Number: cborTagNumForEmbeddedJSON, Content: data, } return cbor.Marshal(tag) } // UnmarshalCBOR 将带 tag 262 的 CBOR 数据项解码为 EmbeddedJSON。 func (v *EmbeddedJSON) UnmarshalCBOR(b []byte) error { var tag cbor.Tag if err : cbor.Unmarshal(b, tag); err ! nil { return err } if tag.Number ! cborTagNumForEmbeddedJSON { return fmt.Errorf(got tag number %d, expect tag number %d, tag.Number, cborTagNumForEmbeddedJSON) } jsonData, isByteString : tag.Content.([]byte) if !isByteString { return fmt.Errorf(got tag content type %T, expect tag content []byte, tag.Content) } return json.Unmarshal(jsonData, v) } // MarshalJSON 将 EmbeddedJSON 编码为 JSON 对象。 func (v EmbeddedJSON) MarshalJSON() ([]byte, error) { return json.Marshal(v.any) } // UnmarshalJSON 解码 JSON 对象。 func (v *EmbeddedJSON) UnmarshalJSON(b []byte) error { dec : json.NewDecoder(bytes.NewReader(b)) dec.UseNumber() return dec.Decode(v.any) }该示例展示了自定义类型实现MarshalCBOR/UnmarshalCBOR即可被 codec 自动调用的扩展机制也是实现 COSE、CWT 等基于 CBOR 标签的协议时的通用模板。八、函数与接口一览与encoding/jsonAPI 相同的常用函数Marshal、UnmarshalNewEncoder、(*Encoder).EncodeNewDecoder、(*Decoder).Decode注意Unmarshal在存在剩余字节时返回ExtraneousDataError因为 RFC 8949 将带剩余字节的 CBOR 数据项视为畸形数据。需要解码第一个数据项并返回剩余字节时请使用UnmarshalFirst。其他实用函数Diagnose、DiagnoseFirst将 CBOR 数据翻译为人可读的 Extended Diagnostic NotationRFC 8610 Appendix GUnmarshalFirst解码第一个 CBOR 数据项并返回剩余字节Wellformed若 CBOR 数据项格式良好则返回 truevalid.go 提供格式良好性检查逻辑。与 Goencoding包一致或可比的接口Marshaler、Unmarshaler、BinaryMarshaler、BinaryUnmarshaler。RawMessage类型可用于延迟 CBOR 解码或预计算 CBOR 编码。流式编解码实现位于 stream.go字节串辅助类型见 bytestring.go。九、安全建议解码非常大或不定长的数据时用 Go 的io.LimitReader限制数据量处理超大数据如区块链的系统可能需要提高默认限制使用DecOptions修改MaxArrayElements、MaxMapPairs、MaxNestedLevels等默认限制例如 README 提到默认MaxNestedLevels为 32tinygo 分支下调至 16。十、标准符合性与数据模型细节该库与 IETF STD 94RFC 8949完全一致同时支持 CBOR SequencesRFC 8742与 Extended Diagnostic NotationRFC 8610 Appendix G。CBOR 特性对照CBOR 特性说明CBOR tagsAPI 支持内置与用户自定义标签Preferred serialization整数编码为最少字节可选 float64 → float32 → float16Map 键排序不排序、长度优先Canonical CBOR、逐字节字典序CTAP2重复 map 键编码时始终禁止解码时可选允许/禁止不定长数据编码与解码均可选允许/禁止格式良好性始终检查并强制基本有效性检查可选检查 UTF-8 有效性与重复 map 键安全考量防止整数溢出与资源耗尽RFC 8949 Section 10数据模型细节Go 的 nil 切片、map、指针等编码为 CBOR null空切片、空 map 编码为空的 CBOR 数组和 map解码器检查所有必需的格式良好性错误包括各类语法错误子类与数据不足格式良好性验证后基本有效性错误按如下处理无效 UTF-8 字符串——解码器默认开启检查并返回错误map 中的重复键——解码器提供忽略或强制拒绝的选项解码格式良好的 CBOR 数组与 map 时解码器保存遇到的第一个错误并继续处理下一项默认情况下解码器将 NaN 与 Infinity 的浮点时间值视为 CBOR Null 或 Undefined。重复 map 键检测基于将 Go 特定数据模型应用于 CBOR 扩展通用数据模型来判断键是否重复DupMapKeyQuiet关闭检测根据 Go 数据类型在保留第一个或保留最后一个中选择最快的策略DupMapKeyEnforcedAPF强制检测检测到第一个重复键时立即停止解码并返回DupMapKeyError包含重复键与索引号。APF 后缀表示允许部分填充即出错时目标 map 或 struct 可能已包含部分解码值调用方需按协议决定是否丢弃部分结果。内置 tag0、1、2、3、55799会校验 tag 内容的类型与取值是否合格未知 tag 的处理方式解码到空接口时转为cbor.Tag类型解码到其他 Go 类型时转为指定类型若该类型注册了 tag 编号还可选择校验。解码器还提供禁止 tag 数据项的选项如 CTAP2 Canonical CBOR 协议要求。十一、已知局限CBORUndefined0xf7解码为 Go 的 nil 值CBORNull0xf6更接近 Go 的 nil数据类型的 CBOR map 键无法作为 Go map 键时会被忽略并返回错误继续解码剩余项将注册的 CBOR tag 数据解码到接口类型时解码器会创建指向注册 Go 类型的指针要求指针是 Go 语言本身的限制。十二、版本与 API 稳定性仓库中 vendored 的版本为v2.9.0go.mod。项目遵循语义化版本管理除非主版本号变化API 始终向后兼容。以下函数签名与encoding/json完全一致且在重大新版本后仍将保持匹配Marshal、Unmarshal、NewEncoder、NewDecoder、(*Encoder).Encode、(*Decoder).Decode。不纳入 SemVer 承诺的例外标记为subject to change的新增 APImaster 分支上尚未在非 beta 版本中发布的新增 API参数不变但修复行为的 bug 修复会在发布说明中强调并延长 beta 期。除非为提升与所支持 RFC 的一致性所必需项目避免破坏编解码函数的行为不提升标准一致性的可见变化通常以新 opt-in 设置或新函数形式提供。版本要求v2.8.0 及更新版本需要 Go 1.20v2.7.1 及更早版本需要 Go 1.17。v2.5.0 起新增UnmarshalFirst/DiagnoseFirst解码 CBOR Sequencesv2.7.0 起新增MarshalToBuffer与UserBufferEncModev2.8.0 新增omitzero字段标签选项v2.9.0 增强了 CBOR 与 JSON 之间的互操作/转码并新增 opt-in 的encoding.TextMarshaler/TextUnmarshaler及json.Marshaler/Unmarshaler转码支持。从 v2.4 或更早版本升级前应重点阅读 v2.5.0 发布说明中关于Unmarshal多余数据错误处理等行为变更。十三、在 KubeVirt 仓库中的落地形态源码布局完整 vendored 于 vendor/github.com/fxamacker/cbor/v2/核心文件包括 encode.go、decode.go、stream.go、tag.go、valid.go、diagnose.go、structfields.go、cache.go 与 common.go 等构建集成BUILD.bazel 将该库接入 KubeVirt 的 Bazel 构建并附带了 CODE_OF_CONDUCT.md、CONTRIBUTING.md、SECURITY.md 与 MIT LICENSE依赖性质从源码搜索看KubeVirt 自身pkg/与staging/下的业务代码并未直接 import 该库它在 go.mod 中被标记为间接依赖主要由上游 Kubernetes 生态依赖引入用于依赖链中涉及 CBOR 数据如 COSE 签名等基于标签的格式的编解码场景。综上fxamacker/cborv2 为 Go 生态提供了一套安全、快速、符合 RFC 8949/8742/8610 的 CBOR 编解码方案以encoding/json风格 API 降低使用门槛以 Struct Tag 选项、预设与自定义模式、TagSet 扩展机制覆盖从通用序列化到 COSE/CWT/CTAP2 等协议级场景。对于 KubeVirt 这样的大型 Go 项目而言它以 vendored 间接依赖的形式稳定存在于依赖树中是保障 CBOR 数据编解码正确性与安全性的基础设施。赞分享云原生【免费下载链接】kubevirtKubernetes Virtualization API and runtime in order to define and manage virtual machines.项目地址https://gitcode.com/gh_mirrors/ku/kubevirt点击查看免费下载相关推荐KubeEdge 依赖体系中的 Go CBOR 编解码实践fxamacker/cbor v2 全面指南KubeEdge 依赖体系中的 Go CBOR 编解码实践fxamacker/cbor v2 全面指南 CBORConcise Binary Object云原生边缘计算物联网容器编排边缘网关深入解析 fxamacker/cbor v2Go 语言中的 RFC 8949 CBOR 编解码器实战指南深入解析 fxamacker/cbor v2Go 语言中的 RFC 8949 CBOR 编解码器实战指南 本篇文章聚焦 vendor/github.com/f人工智能AI AgentAgent 沙箱云原生容器运行时零信任fxamacker/cbor v2 实战指南在 Go 与 OpenShift 中使用符合 RFC 8949 的 CBOR 编解码库fxamacker/cbor v2 实战指南在 Go 与 OpenShift 中使用符合 RFC 8949 的 CBOR 编解码库 导读 本文以 OpenSh测试云原生质量保障上一篇FGA完整使用指南5个步骤实现FGO自动刷本彻底解放双手下一篇3个步骤轻松搞定PDF文件对比diff-pdf让你的文档核对效率翻倍创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?