Protobuf vs CBOR:新一代的二進(jìn)制序列化格式
在以前的文章中,我們講到了什么時(shí)候用 Yaml,什么時(shí)候用 JSON,什么時(shí)候用 Protobuf:
- 人寫(xiě)機(jī)器讀,用 Yaml
- 機(jī)器寫(xiě),人讀,用 JSON
- 機(jī)器寫(xiě),機(jī)器讀,用 JSON 或者 Protobuf
JSON 作為幾乎每一個(gè)語(yǔ)言都支持的序列化格式,在很多地方都得到了廣泛應(yīng)用。但有個(gè)弊端,JSON 里面充斥了大量的大括號(hào)、中括號(hào)和雙引號(hào),導(dǎo)致冗余的字符太多,數(shù)據(jù)量非常大,在對(duì)傳輸速度有高要求的場(chǎng)景下,數(shù)據(jù)量越大,占用的傳輸帶寬就越大,單位時(shí)間傳輸?shù)臄?shù)據(jù)也就越少。
Protobuf 是 Google 開(kāi)發(fā)的一個(gè)二進(jìn)制序列化格式,與 JSON 相比,Protobuf 的數(shù)據(jù)非常精簡(jiǎn),甚至連數(shù)據(jù)的字段名都沒(méi)有。例如有這樣一段數(shù)據(jù):
- a = {'name': 'kingname', 'salary': 99999, 'address': '上海', 'skill': ['Python', '爬蟲(chóng)', 'Golang']}
如果用 Protobuf 來(lái)表示,那么數(shù)據(jù)的二進(jìn)制形式是這樣的:
這個(gè)二進(jìn)制數(shù)據(jù)只有值,但沒(méi)有字段名,所以要解析這些數(shù)據(jù),必須在代碼里面額外把字段名帶上。所以需要定義一個(gè)xxx.proto文件,在里面標(biāo)記每一個(gè)字段的信息。在任何時(shí)候任何語(yǔ)言中,需要序列化和反序列化的地方,都要提前使用protoc命令,基于這個(gè).proto文件,生成一個(gè)xxx_pb2文件,通過(guò)從這個(gè) xxx_pb2文件中導(dǎo)入數(shù)據(jù)對(duì)象來(lái)對(duì)數(shù)據(jù)進(jìn)行處理。
因此,我們說(shuō),proto 格式,雖然確實(shí)精簡(jiǎn)了網(wǎng)絡(luò)中的數(shù)據(jù)傳輸量,但卻給開(kāi)發(fā)者增加了相當(dāng)大的工作量。
而最近,又新出來(lái)一種二進(jìn)制序列化格式:CBOR,它的數(shù)據(jù)比 JSON 小,但是開(kāi)發(fā)起來(lái)又比 Protobuf 簡(jiǎn)單得多。
我們來(lái)看看使用 CBOR 對(duì)上面的數(shù)據(jù)進(jìn)行序列化操作。首先在 Python 中安裝CBOR:
- python3 -m pip install cbor2
安裝完成以后,我們來(lái)對(duì)數(shù)據(jù)進(jìn)行序列化:
- import cbor2
- a = {'name': 'kingname', 'salary': 99999, 'address': '上海', 'skill': ['Python', '爬蟲(chóng)', 'Golang']}
- result = cbor2.dumps(a)
- print(result)
運(yùn)行效果如下圖所示:
注意,打印出來(lái)的是二進(jìn)制數(shù)據(jù),不是字符串??梢钥吹剑瑪?shù)據(jù)是自帶字段名的,字段名與值之間會(huì)有特殊的字符進(jìn)行分割,CBOR 能夠自動(dòng)識(shí)別這些特殊符號(hào),從而區(qū)分字段名和字段值。
經(jīng)過(guò)我的測(cè)試,一個(gè)150MB 的大 JSON文件,讀入到內(nèi)存,然后重新通過(guò) CBOR 序列化以后寫(xiě)文件,這個(gè)文件大小可以縮減到60MB 左右。雖然壓縮比例不如 Protobuf,可讀性不如 JSON;但是壓縮比例比 JSON 高,可讀性比 Protobuf 好,而且?guī)缀醪辉黾宇~外工作量。
大家在寫(xiě)微服務(wù)或者網(wǎng)站前后端通信的時(shí)候,可以考慮試一試 CBOR — Concise Binary Object Representation | Overview[1]。
參考資料
[1]CBOR — Concise Binary Object Representation | Overview: https://cbor.io/
本文轉(zhuǎn)載自微信公眾號(hào)「未聞Code」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系未聞Code公眾號(hào)。