Lyft 分享了使用 Protocol Buffers 进行系统间集成的经验,主要关注于协作式的协议设计,以便于在团队和系统间共享定义。该公司倡导的方法是提高知识共享、一致性和开发流程质量,而不是原始的效率优化。
Lyft 已经采用 Protocol Buffers 很久了,在 2020 年,该公司介绍了从 HTTP+JSON 迁移至该方案的原因,列举了 ProtoBuf 作为接口定义语言(Interface Definition Language,IDL)的可描述性、适用于大多数语言的开源代码生成器、优化的二进制格式以及向后兼容 JSON API 的能力。
在三种语言技术栈(Python、Swift 和 Kotlin)中使用 Protocol Buffers 多年后,工程师们在协议定义设计方面积累了丰富的经验,尤其是跨团队和系统工作时,往往会遇到不熟悉 Protobuf 的同事。Lyft 的软件工程师 Roman Kotenko 提出了协议设计的关键原则:
清晰性:设计良好的协议在定义消息时,要明确哪些字段必须要设置。这样可以防止在实现过程中漏掉某些信息。换句话说,好的协议不会给实现者留下任何模糊不清的地方。
可扩展性:协议结构的构建必须要考虑到未来的愿景和潜在的发展路线图。这样,一些可预见的新增内容和破坏性变更就可以提前考虑到。
除此之外,Kotenko 还在文章中给出了一些最佳实践,Lyft 认为这些最佳实践对于采用 Protocol Buffers 作为广泛使用的分布式系统的接口定义语言(IDL)至关重要。
作者强调了使用 Protocol Buffers 的消息校验功能的收益。protovalidate 项目是一个基于用户定义的校验规则在运行时校验消息的推荐方式。它是 protoc-gen-validate 插件的后续版本(由 Lyft 创建,依然在 Lyft 内使用),由谷歌的 通用表达式语言(Common Expression Language,CEL) 提供支撑。该方案支持多种校验规则,可用于不同类型的消息和字段,如 unions(oneof)、enums、collections(repeated)、maps 和 scalars,包括封装类型。
Lyft 团队创建了一种方式,用来统一在协议定义中跨多个实体的常量值。Kotenko 展示了如何为实现该目而使用的自定义方案,但是他也警告采用该方案的注意事项,包括对协议定义用户的完全控制要求(例如,在内部使用协议的情况)。
Protocol Buffers 消息定义的样例(图片来源:Lyft 的工程博客)
其他的最佳实践也反映在了官方文档中,比如,在通用的用例中使用众人熟知的数据类型,包括未知的枚举值,以及利用 Protobuf 3.15 引入的新“optional”标签明确标记可选字段。
最后,作者指出,查看特定语言的教程对于了解所需的设置和所有微妙的细节(比如,类型映射和代码生成特性)至关重要,因为不同语言的某些行为是不同的。
查看英文原文:
https://www.infoq.com/news/2024/09/lyft-protocol-buffers-design/
评论