领英采用 Protobuf,以实现其各类平台中更为高效的微服务间数据传递,并将其与开源框架 Rest.li 相集成。在全公司范围的推广完成后,领英将延迟降低了 60%的同时,也提高了资源的利用率。
领英平台所采用的是微服务架构,而多年以来,JSON 一直都是领英在微服务暴露的五万余 API 节点中所使用的序列化格式。为帮助团队在服务间构建一致性交互,领英创建并开源了一款名为 Rest.li 的 Java 框架。
该框架可用于创建使用 REST 通信风格的服务器和客户端,并抽象网络、序列化、服务发现等数据交换的诸多方面。Rest.li 框架主要支持 Java 和 Python,但也可与 Scala、Kotlin、JavaScript、Go 等语言协同运作。
Rest.li 的默认序列化格式为 JSON,这种格式支持多款语言且易于人类阅读,后者虽然好处甚多,但却给性能(尤其是延迟)方面带来了许多问题。
领英工程师 Karthik Ramgopal 和 Aman Gupta 分享了在使用 JSON 进行服务间通信所要面临的挑战:
第一个挑战在于,JSON 作为一款文本格式往往过于冗长,从而导致网络带宽的使用和延迟增加,效果并不理想。(……)我们所面临的第二个挑战则在于,JSON 的文本性质会导致序列化和反序列化的延迟和吞吐量均不甚理想。
领英团队一直在寻求 JSON 的替代方案,一款负载大小紧凑、系列化效率高,可减少延迟并提升吞吐量的方案。他们同时也希望这款方案不会限制所支持的语言栈数量,并能通过将这个新的序列化机制集成至 Rest.li 从而实现逐步迁移。最后,经过全面的思考,领英决定采用在各项考量中综合得分最高的Protobuf。
将 Protobuf 集成到 Rest.li 中的主要困难在于 PDL,一个基于框架的自定义模式定义系统的动态模式生成。这套解决方案中需生成一个用于动态生成 Protobuf 模式定义的符号表,但根据客户端类型的不同,符号表的交付方式也会有所不同。后端客户端按需获取并缓存符号表,而网页或移动端应用的符号表则在构建时生成,且其中包含版本号依赖关系。
在对框架进行修改之后,领英团队通过 HTTP 头逐步对客户端进行重新配置,以 Protobuf 替代 JSON。采用 Protobuf 后,响应的吞吐量平均提高了 6.25%,请求的吞吐量平均提高了 1.77%。领英团队同样发现对大型负载而言,延迟降低了 60%。
根据对 Protobuf 的采用所得来的经验,领英团队计划后续将 Rest.li 迁移至 gRPC。gRPC 同样使用 Protobuf,并额外支持流式传输,其背后还有一个庞大社区的支持。
参考文档:https://www.infoq.com/news/2023/07/linkedin-protocol-buffers-restli/