热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

protobuf使用心得:解析与编码陷阱

本文记录了一次在广告系统中使用protobuf进行数据交换时遇到的问题及其解决过程。通过这次经历,我们将探讨protobuf的特性和编码机制,帮助开发者避免类似的陷阱。

da6b5c36a6e6d368d04c4bbc6afacd9e.png

本文旨在分享在广告系统开发中使用protobuf时遇到的一个具体问题及其解决方案。通过详细分析,希望能帮助读者更好地理解和应用protobuf。


在高性能需求的广告系统中,毫秒级的延迟优化至关重要。为了提高效率,我们选择了protobuf作为与外部媒体通信的数据格式,相较于JSON和XML,它能显著减少编解码时间和网络传输成本。然而,这种高效也伴随着一定的不便,如无法直接通过文本编辑器查看或修改数据,且问题排查难度增加。


- 遇到的问题 -

7月,一家媒体提出希望一次请求能获取多条广告,以便更好地适应信息流场景。为此,我们在Impression类型中添加了一个ads_count字段,用于指定所需广告的数量。按照常规流程更新了.proto文件,并生成了新的Go语言代码。然而,无论媒体请求中填写的具体数值如何,我们始终只能解码出ads_count为1的结果。


- 问题排查 -

鉴于我们的代码已经过测试,能够正确处理ads_count,初步怀疑问题出在媒体的请求上。通过录制并保存请求至req.pb文件,使用protoc --decode-raw命令尝试解码,但结果难以解读。随后,利用已知的.proto文件进行更精确的解码,发现了一个未在定义中出现的字段10: 3,这提示我们双方的.proto文件存在差异。


- 解决方案 -

经过与媒体的沟通确认,他们确实曾在ads_count之前添加了另一个字段。调整我们的.proto文件,将ads_count的序号改为10,重新编译并测试,问题得以解决。


- 编码机制简介 -

为加深理解,这里简要介绍protobuf的编码机制。每个字段在编码时会根据其序号和类型生成一个键值对,其中键由字段序号和类型标识组成,值则是实际的数据。例如,对于简单的Test1类型:

message Test1 {  optional int32 a = 1;}

当给a赋值150并序列化时,会生成三个字节的数据:08 96 01。首字节08的二进制形式为0000 1000,其中最低三位000表示这是一个varint类型,接下来四位0001表示字段序号1,最高位0表示这是最后一个字节。后续两个字节96 01则表示了实际的值150,遵循varint的小端存储规则。


- 关于负整数的编码 -

对于负整数,protobuf采用了特殊的ZigZag编码方式,以确保较小的负数也能被高效编码。这种方式通过交替使用正负数来表示连续的整数,从而实现更紧凑的编码。


- 结语 -

通过这次经历,我们不仅解决了实际问题,还深入理解了protobuf的工作原理。更多关于字符串、嵌套类型及数组的编码细节,建议参考官方文档。

最后,留给大家一个小练习:下面的编码数据表示了什么?12 03 36 36 36


推荐阅读:

  • 《程序员面试指南:从面试官角度看问题》
  • 《Go服务性能优化案例:内存激增问题的解决》
  • 《技术交流中的日志问题与沟通技巧》
  • 《C++面试难题解析》

5295a4be53445f8c560ef345ccbc5257.png


推荐阅读
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • golang常用库:配置文件解析库/管理工具viper使用
    golang常用库:配置文件解析库管理工具-viper使用-一、viper简介viper配置管理解析库,是由大神SteveFrancia开发,他在google领导着golang的 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 本文详细介绍了如何在Linux系统上安装和配置Smokeping,以实现对网络链路质量的实时监控。通过详细的步骤和必要的依赖包安装,确保用户能够顺利完成部署并优化其网络性能监控。 ... [详细]
  • XNA 3.0 游戏编程:从 XML 文件加载数据
    本文介绍如何在 XNA 3.0 游戏项目中从 XML 文件加载数据。我们将探讨如何将 XML 数据序列化为二进制文件,并通过内容管道加载到游戏中。此外,还会涉及自定义类型读取器和写入器的实现。 ... [详细]
  • 本文详细探讨了KMP算法中next数组的构建及其应用,重点分析了未改良和改良后的next数组在字符串匹配中的作用。通过具体实例和代码实现,帮助读者更好地理解KMP算法的核心原理。 ... [详细]
  • 深入解析Android自定义View面试题
    本文探讨了Android Launcher开发中自定义View的重要性,并通过一道经典的面试题,帮助开发者更好地理解自定义View的实现细节。文章不仅涵盖了基础知识,还提供了实际操作建议。 ... [详细]
  • Explore how Matterverse is redefining the metaverse experience, creating immersive and meaningful virtual environments that foster genuine connections and economic opportunities. ... [详细]
  • 本文详细介绍如何使用Python进行配置文件的读写操作,涵盖常见的配置文件格式(如INI、JSON、TOML和YAML),并提供具体的代码示例。 ... [详细]
  • 本文介绍了Java并发库中的阻塞队列(BlockingQueue)及其典型应用场景。通过具体实例,展示了如何利用LinkedBlockingQueue实现线程间高效、安全的数据传递,并结合线程池和原子类优化性能。 ... [详细]
  • 1.如何在运行状态查看源代码?查看函数的源代码,我们通常会使用IDE来完成。比如在PyCharm中,你可以Ctrl+鼠标点击进入函数的源代码。那如果没有IDE呢?当我们想使用一个函 ... [详细]
  • 本文详细介绍了如何使用Spring Boot进行高效开发,涵盖了配置、实例化容器以及核心注解的使用方法。 ... [详细]
  • 本文探讨了 Objective-C 中的一些重要语法特性,包括 goto 语句、块(block)的使用、访问修饰符以及属性管理等。通过实例代码和详细解释,帮助开发者更好地理解和应用这些特性。 ... [详细]
  • 本文介绍如何使用阿里云的fastjson库解析包含时间戳、IP地址和参数等信息的JSON格式文本,并进行数据处理和保存。 ... [详细]
  • andr ... [详细]
author-avatar
呼吸乱了的声音_648
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有