概述
Protocol buffers 提供了一種語(yǔ)言中立、平臺(tái)中立、可擴(kuò)展的機(jī)制,用于以向前兼容和向后兼容的方式序列化結(jié)構(gòu)化數(shù)據(jù)。 它類似于 JSON,只是它更小更快,并且可以按指定語(yǔ)言生成。
Protocol buffers 解決了什么問題?
Protocol buffers 為大小高達(dá)幾兆字節(jié)的類型化結(jié)構(gòu)化數(shù)據(jù)包提供了一種序列化格式。 該格式適用于臨時(shí)網(wǎng)絡(luò)流量和長(zhǎng)期數(shù)據(jù)存儲(chǔ)。 可以使用新信息擴(kuò)展 protocol buffers,而無需使現(xiàn)有數(shù)據(jù)無效或需要更新代碼。
Protocol buffers 是 Google 最常用的數(shù)據(jù)格式。 它們廣泛用于服務(wù)器間通信以及磁盤上數(shù)據(jù)的歸檔存儲(chǔ)。 Protocol buffer message 和 service 由工程師編寫的 .proto 文件描述。
proto 編譯器在 .proto 文件的構(gòu)建時(shí)被調(diào)用,以生成各種編程語(yǔ)言的代碼(在本主題后面的跨語(yǔ)言兼容性中介紹)來操作相應(yīng)的 protocol buffer。 每個(gè)生成的類都包含:每個(gè)字段的簡(jiǎn)單訪問器、用于序列化和解析整個(gè)結(jié)構(gòu)與原始數(shù)據(jù)之間關(guān)系的方法。
由于 protocol buffer 在 Google 的各種服務(wù)中廣泛使用,并且其中的數(shù)據(jù)可能會(huì)保留一段時(shí)間,因此保持向后兼容性至關(guān)重要。 protocol buffer 支持更改,包括添加新字段和刪除現(xiàn)有字段,而不會(huì)破壞現(xiàn)有服務(wù)。
使用 Protocol buffer 有哪些好處?
最常用于定義通信協(xié)議(與 gRPC 一起)和數(shù)據(jù)存儲(chǔ)。
使用 protocol buffer 的一些優(yōu)點(diǎn)包括:
- 數(shù)據(jù)壓縮存儲(chǔ)
- 快速解析
- 支持多種編程語(yǔ)言
- 通過自動(dòng)生成的類優(yōu)化功能
跨語(yǔ)言兼容性
可以通過編寫任何支持的編程語(yǔ)言,來讀取相同的消息。
例如, 可以讓一個(gè)平臺(tái)上的 Java 程序,根據(jù) .proto 定義對(duì)數(shù)據(jù)進(jìn)行序列化,然后在另一個(gè)平臺(tái)上運(yùn)行的單獨(dú) Python 應(yīng)用程序,從序列化數(shù)據(jù)中提取特定值。
跨項(xiàng)目支持
可以使用特定項(xiàng)目代碼庫(kù)之外的 .proto 文件中定義消息類型,來跨項(xiàng)目使用 protocol buffer。
在不更新代碼的情況下更新 Proto 定義
軟件產(chǎn)品向后兼容是標(biāo)準(zhǔn),但向前兼容卻不太常見。 只要您在更新 .proto 定義時(shí)遵循一些簡(jiǎn)單的做法,舊代碼將毫無問題地讀取新消息,而忽略任何新添加的字段。 對(duì)于舊代碼,刪除的字段將具有默認(rèn)值,刪除的重復(fù)字段將為空。
新代碼也將透明地讀取舊消息。 舊消息中不會(huì)出現(xiàn)新字段; 在這些情況下, protocol buffer 提供了一個(gè)合理的默認(rèn)值。
什么時(shí)候 protocol buffer 不適用?
Protocol buffer 并不是適用于所有數(shù)據(jù),尤其是:
protocol buffer 傾向于 假設(shè)整個(gè)消息可以一次加載到內(nèi)存中,并且不大于一個(gè) object graph。 對(duì)于超過幾兆字節(jié)的數(shù)據(jù),考慮不同的解決方案; 在處理較大的數(shù)據(jù)時(shí),由于序列化副本,您可能會(huì)有效地獲得多個(gè)數(shù)據(jù)副本,這可能會(huì)導(dǎo)致內(nèi)存使用量出現(xiàn)驚人的峰值。
當(dāng) protocol buffer 被序列化時(shí),相同的數(shù)據(jù)可以有許多不同的二進(jìn)制序列化。 如果不完全解析它們,就無法比較兩條消息的相等性。
消息未壓縮。 雖然消息可以像任何其他文件一樣被壓縮,但專用壓縮算法(如 JPEG 和 PNG 使用的壓縮算法)將為適當(dāng)類型的數(shù)據(jù)生成小得多的文件。
對(duì)于涉及大型多維浮點(diǎn)數(shù)數(shù)組的許多科學(xué)和工程用途,protocol buffer 消息在大小和速度方面都沒有達(dá)到最大效率。 對(duì)于這些應(yīng)用程序,F(xiàn)ITS 和類似格式的開銷較小。
Protocol buffer 在科學(xué)計(jì)算中流行的非面向?qū)ο笳Z(yǔ)言(例如 Fortran 和 IDL)中沒有得到很好的支持。
Protocol buffer 消息本身并不自我描述其數(shù)據(jù),但它們具有完全反射的模式,您可以使用它來實(shí)現(xiàn)自我描述。 也就是說,如果不訪問其相應(yīng)的 .proto 文件,您將無法完全解釋它。
Protocol buffer 不是任何組織的正式標(biāo)準(zhǔn)。 這使得它們不適合在具有法律或其他要求以建立在標(biāo)準(zhǔn)之上的環(huán)境中使用。
Protocol buffer 是如何工作的?

- protocol buffer 工作流程
protocol buffer 生成的代碼,提供了從文件和流中檢索數(shù)據(jù)、從數(shù)據(jù)中提取單個(gè)值、檢查數(shù)據(jù)是否存在、將數(shù)據(jù)序列化回文件或流、以及其他有用功能的實(shí)用方法。
Protocol buffer 定義語(yǔ)法
定義 .proto 文件時(shí),您可以指定字段是 optional 或 repeated(proto2 和 proto3)或 singular(proto3)。 (將字段設(shè)置為 required 選項(xiàng)在 proto3 中不存在,并且在 proto2 中強(qiáng)烈建議不要使用)
設(shè)置字段的 可選性/可重復(fù)性 后,指定數(shù)據(jù)類型。Protocol buffer 支持通常的原始數(shù)據(jù)類型,例如 integers、booleans、floats。
一個(gè)字段也可以是:
- message 類型,以便您可以嵌套部分定義,例如用于重復(fù)數(shù)據(jù)集。
- enum 類型,因此您可以指定一組值以供選擇。
- oneof 類型,當(dāng)消息有多個(gè)可選字段且最多同時(shí)設(shè)置一個(gè)字段時(shí),可以使用該類型。
- map 類型,用于將鍵值對(duì)添加到您的定義中。
在設(shè)置 可選性 和 字段類型 后,分配一個(gè)字段編號(hào)。 字段編號(hào)不能改變用途或重復(fù)使用。 如果您刪除一個(gè)字段,您應(yīng)該保留其字段編號(hào),以防止有人意外重復(fù)使用該編號(hào)。
額外支持的數(shù)據(jù)類型
Protocol buffer 支持許多標(biāo)量值類型,包括使用可變長(zhǎng)度編碼和固定大小的整數(shù)。 您還可以通過定義消息來創(chuàng)建自己的復(fù)合數(shù)據(jù)類型,這些消息本身就是可以分配給字段的數(shù)據(jù)類型。 除了簡(jiǎn)單和復(fù)合值類型之外,還發(fā)布了幾種常見類型。
常見類型
- Duration
Duration 是有符號(hào)的、固定長(zhǎng)度的時(shí)間跨度,例如 42s。 - Timestamp
Timestamp 是獨(dú)立于任何時(shí)區(qū)或日歷的時(shí)間點(diǎn),例如 2017-01-15T01:30:15.01Z。 - Interval
Interval 是獨(dú)立于時(shí)區(qū)或日歷的時(shí)間間隔,例如 2017-01-15T01:30:15.01Z - 2017-01-16T02:30:15.01Z。 - Date
Date 是一個(gè)完整的日歷日期,例如 2025-09-19。 - DayOfWeek
DayOfWeek 是一周中的某一天,例如 Monday。 - TimeOfDay
TimeOfDay 是一天中的某個(gè)時(shí)間,例如 10:42:23。 - LatLng
LatLng 是一個(gè)緯度/經(jīng)度對(duì),例如 37.386051 緯度和 -122.083855 經(jīng)度。 - Money
money 是具有貨幣類型的貨幣數(shù)量,例如 42 USD。 - PostalAddress
PostalAddress 是郵政地址,例如 1600 Amphitheatre Parkway Mountain View, CA 94043 USA。 - Color
Color 是 RGBA 顏色空間中的一種顏色。 - Month
Month 是一年中的一個(gè)月,例如 April。