热门标签 | 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


推荐阅读
  • 本文深入探讨了HTTP请求和响应对象的使用,详细介绍了如何通过响应对象向客户端发送数据、处理中文乱码问题以及常见的HTTP状态码。此外,还涵盖了文件下载、请求重定向、请求转发等高级功能。 ... [详细]
  • 本文详细介绍如何在VSCode中配置自定义代码片段,使其具备与IDEA相似的代码生成快捷键功能。通过具体的Java和HTML代码片段示例,展示配置步骤及效果。 ... [详细]
  • golang常用库:配置文件解析库/管理工具viper使用
    golang常用库:配置文件解析库管理工具-viper使用-一、viper简介viper配置管理解析库,是由大神SteveFrancia开发,他在google领导着golang的 ... [详细]
  • 深入理解Cookie与Session会话管理
    本文详细介绍了如何通过HTTP响应和请求处理浏览器的Cookie信息,以及如何创建、设置和管理Cookie。同时探讨了会话跟踪技术中的Session机制,解释其原理及应用场景。 ... [详细]
  • 本文介绍如何使用阿里云的fastjson库解析包含时间戳、IP地址和参数等信息的JSON格式文本,并进行数据处理和保存。 ... [详细]
  • 最近团队在部署DLP,作为一个技术人员对于黑盒看不到的地方还是充满了好奇心。多次咨询乙方人员DLP的算法原理是什么,他们都以商业秘密为由避而不谈,不得已只能自己查资料学习,于是有了下面的浅见。身为甲方,虽然不需要开发DLP产品,但是也有必要弄明白DLP基本的原理。俗话说工欲善其事必先利其器,只有在懂这个工具的原理之后才能更加灵活地使用这个工具,即使出现意外情况也能快速排错,越接近底层,越接近真相。根据DLP的实际用途,本文将DLP检测分为2部分,泄露关键字检测和近似重复文档检测。 ... [详细]
  • 深入理解Shell脚本编程
    本文详细介绍了Shell脚本编程的基础概念、语法结构及其在操作系统中的应用。通过具体的示例代码,帮助读者掌握如何编写和执行Shell脚本。 ... [详细]
  • 本文介绍了一种从与src同级的config目录中读取属性文件内容的方法。通过使用Java的Properties类和InputStream,可以轻松加载并获取指定键对应的值。 ... [详细]
  • 本文详细介绍了如何使用 Yii2 的 GridView 组件在列表页面实现数据的直接编辑功能。通过具体的代码示例和步骤,帮助开发者快速掌握这一实用技巧。 ... [详细]
  • 使用 Azure Service Principal 和 Microsoft Graph API 获取 AAD 用户列表
    本文介绍了一段通用代码示例,该代码不仅能够操作 Azure Active Directory (AAD),还可以通过 Azure Service Principal 的授权访问和管理 Azure 订阅资源。Azure 的架构可以分为两个层级:AAD 和 Subscription。 ... [详细]
  • 深入解析Spring Cloud Ribbon负载均衡机制
    本文详细介绍了Spring Cloud中的Ribbon组件如何实现服务调用的负载均衡。通过分析其工作原理、源码结构及配置方式,帮助读者理解Ribbon在分布式系统中的重要作用。 ... [详细]
  • 本文详细介绍了 Apache Jena 库中的 Txn.executeWrite 方法,通过多个实际代码示例展示了其在不同场景下的应用,帮助开发者更好地理解和使用该方法。 ... [详细]
  • 根据最新发布的《互联网人才趋势报告》,尽管大量IT从业者已转向Python开发,但随着人工智能和大数据领域的迅猛发展,仍存在巨大的人才缺口。本文将详细介绍如何使用Python编写一个简单的爬虫程序,并提供完整的代码示例。 ... [详细]
  • 本文探讨了领域驱动设计(DDD)的核心概念、应用场景及其实现方式,详细介绍了其在企业级软件开发中的优势和挑战。通过对比事务脚本与领域模型,展示了DDD如何提升系统的可维护性和扩展性。 ... [详细]
  • 本文探讨了如何在 PHP 的 Eloquent ORM 中实现数据表之间的关联查询,并通过具体示例详细解释了如何将关联数据嵌入到查询结果中。这不仅提高了数据查询的效率,还简化了代码逻辑。 ... [详细]
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社区 版权所有