成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

一個 bug 竟然是 Protobuf 的 feature

開發 前端
既然知道 protobuf 會這么操作,那我們就只要知道 protobuf 怎么分割就行了。這個方法還真不好找,因為像我們這樣使用的人太少了。中文搜索完全搜不到這一塊的內容,可能大家都不會使用protobuf來存儲數據吧,大家使用的方式應該都是多個服務中進行交互的場景吧。

大家好,我是了不起。

最近我們在項目中,通過使用 protobuf 格式作為存儲數據的一個載體。一個不小心就給自己埋了個大坑,還是過了好久才發現。

protobuf 簡介

protobuf 全名叫 Protocal buffers. 它是由 Google 研發的,一種可跨語言、可跨平臺、可擴展的序列化數據的機制。類似于 XML ,但是它更小、更快、更簡單。你只需要定義一次你希望的數據如何被結構化,然后你可以使用它的生成工具,生成包含一些序列化和反序列化等操作的源代碼。可以輕松地從各種數據流和使用各種編程語言寫入和讀取結構化的數據。

proto2版本支持在Java、Python、Objective-C和C++中生成代碼。使用新的proto3語言版本,你還可以使用Kotlin、Dart、Go、Ruby、PHP和C#,還有更多的語言。

怎么發現的?

在我們的新項目中,我們通過使用 protobuf 格式來存儲項目運行的數據。這樣我們在調試過程中,可能根據現場錄制的數據進行本地的調試。

message ImageData {
// ms
int64 timestamp = 1;
int32 id = 2;
Data mat = 3;
}

message PointCloud {
// ms
int64 timestamp = 1;
int32 id = 2;
PointData pointcloud = 3;
}

message State {
// ms
int64 timestamp = 1;
string direction = 2;
}

message Sensor {
repeated PointCloud point_data = 1;
repeated ImageData image_data = 2;
repeated State vehicle_data = 3;
}

我們定義了這樣一組數據, 然后存儲的時候,因為Sensor 這3個數據源的幀率不一樣,因此存儲的時候,單個 Sensor 中其實只包含了一組數據,另外兩個類型的數據并沒有包含進去。

當我們只錄制單個 pack 的時候,我們并沒有遇到問題。直到我們覺得單個包,不能長時間錄制,我們需要找一種解決方法來分割包 。

當時覺得這個一定是很簡單的,我們就設定了一個包達到 500M 的時候,我們就讓后面的數據存到新的包中。很順利的寫完,然后放到現場進行數據錄制。錄制一段時間之后,我們把包拿回來進行模擬測試我們的新程序。發現有些包的數據解析出來是有問題的。程序運行到一半會卡在那里不動。經過多次測試,發現是部分包有這個問題。

我們一開始懷疑的是,判斷文件大小的方式不對,影響到了分包。因為判斷文件大小的時候,會去打開文件。但是經過好幾種其他的不打開文件的方式判斷,從而進行分割。還是遇到了部分錄制的包有問題。

這時我才懷疑到 protobuf 對存儲數據會有一些特殊的要求。后來看了一些文章,了解到 protobuf 存儲多組數據到一個文件需要有標志符。要不然后面從文件解析回來的時候,protobuf 因為不知道單個數據的停止符在哪里,導致數據解析出錯。

到這里,這個坑出現了。我們存儲了一系列的數據到單個包中,沒有做任何分隔符的操作。protobuf在解析的時候,把文件中所有的內容都解析成了單個Sensor。Sensor 中包含里所有數據, protobuf 主動合并了所有存儲的數據。

在這時,我才發現以前單包錄制的時候,數據都是對的,那真的是我運氣好。protobuf恰好解析成功了。

怎么解決呢?

既然知道 protobuf 會這么操作,那我們就只要知道 protobuf 怎么分割就行了。這個方法還真不好找,因為像我們這樣使用的人太少了。中文搜索完全搜不到這一塊的內容,可能大家都不會使用protobuf來存儲數據吧,大家使用的方式應該都是多個服務中進行交互的場景吧。

最終通過stackoverflow上的一些回答找到了答案,從回答中得知,這個解決辦法在 protobuf 3.3 的時候,才正式被合并進去。看起來這個功能真的很少用啊。

bool SerializeDelimitedToOstream(const MessageLite& message,
std::ostream* output);
bool ParseDelimitedFromZeroCopyStream(
MessageLite* message, io::ZeroCopyInputStream* input, bool* clean_eof);

通過這一對方法,可以對文件進行按照數據流一個一個的存儲讀取。再也不用擔心數據被合并讀取。

當然通過這種方式存儲的數據,不能被原來的解析方式所解析,存儲的而進行格式完全變了。這種方式會先存儲二進制數據的大小,再存儲二進制數據。

結束語

經過一番折騰,終于搞定了這個分割的坑。使用場景可能比較小眾,導致了很多資料根本找不到。靠自己看源碼才發現這些問題。C++ 的源碼真不好讀,有很多的模板方法、模板類容易錯過一些細節。最后還是看的C#的代碼,才完全確認的。

責任編輯:武曉燕 來源: Java技術指北
相關推薦

2016-10-25 10:00:20

科技新聞早報

2020-06-17 10:52:30

運維故障技術

2020-09-29 06:45:49

JDK

2020-11-12 09:15:16

GitHubPython開發

2015-06-18 11:04:58

2020-12-15 08:05:40

路由器服務器網絡層

2021-07-28 06:51:08

Nacos代理模式

2024-08-05 01:28:26

2024-09-27 11:38:49

2021-03-04 19:29:28

程序員Unix系統

2021-10-18 13:42:52

加密貨幣金融工具

2021-07-21 08:37:55

AI 裁判人工智能

2018-07-06 00:09:47

2019-03-06 12:26:42

密碼安全數據

2020-10-20 17:18:00

戴爾

2022-07-07 19:44:22

Python 3.1

2021-08-28 10:15:26

項目結構Flask

2020-09-17 11:02:58

Go 開源技術

2023-10-25 15:11:15

Java
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品99久久久精品免费观看 | 国产精品黄色 | 国产高清精品在线 | 午夜视频网站 | 91精品久久久久久久久久 | 先锋影音资源网站 | 久久久久国产精品一区二区 | 黄色激情毛片 | 欧美视频精品 | 欧美成人激情 | 久久青青| 亚洲高清视频一区二区 | 国产aⅴ | 国产精品久久久久久久久 | 精品欧美乱码久久久久久1区2区 | 超碰97人人人人人蜜桃 | 天天操欧美| 97伦理电影网 | 亚洲国产中文字幕 | 精品久久av| 国产精品亚洲一区二区三区在线观看 | 亚洲精品视频免费 | 中文字幕97| 亚洲电影一区 | 久草在线 | 中文在线a在线 | 99国内精品久久久久久久 | 日本成人中文字幕 | a视频在线观看 | 亚洲国产欧美一区二区三区久久 | 欧美国产视频一区二区 | 国产精品观看 | 狠狠操天天干 | 久久久日韩精品一区二区三区 | 不卡一区二区三区四区 | 精品成人在线观看 | 最新免费视频 | 国产视频精品视频 | 国产精品jizz在线观看老狼 | 国产精品久久久久久久久久久免费看 | 亚洲成人99 |