gRPC in ASP.NET Core 3.x -- Protocol Buffer(3)更新消息類型

當你第一次定義Protocol Buffer的消息的時候,你確定會給消息設定一套規則需求。可是隨着時間的推動,你的業務可能會發生了變化,與此同時,你的Protocol Buffer消息類型的需求也會隨之變化。
也就是說:有一些字段可能會發生變化,可能會添加一些字段,也可能會刪除一些字段。可是可能有不少程序正在使用/讀取你的Protocol Buffer的消息,可是它們無法都隨着需求進行更新。因此,在你對源數據進行演進的時候,必定不要引發破壞性變化,不然其它的程序可能就沒法正常工做了。
 
主要有這兩種情景:
  1. 向前兼容變動:使用新的.proto文件來寫數據 --- 從舊的.proto文件讀取數據 
  2. 向後兼容變動:使用舊的.proto文件來寫數據 --- 重新的.proto文件讀取數據
有時候這兩種狀況同時存在,也就是全兼容變動。
 
爲了達到此目的,Protocol Buffer制定了一些更新消息類型的規則:
  1. 不要修改任何現有字段的數字(tag)
  2. 你能夠添加新的字段,那些使用舊的消息格式的代碼仍然能夠將消息序列化,您應該注意這些元素的默認值,以便新代碼能夠與舊代碼生成的消息正確交互。相似的,新代碼所建立的消息也能夠被舊代碼解析:舊的二進制在解析的時候會忽略新的字段。
  3. 字段能夠被刪除,只要它們的數字(tag)在更新後的消息類型中再也不使用便可。你也能夠把字段名改成使用「OBSOLETE_」前綴而不是刪除字段,或者把這些字段的數字(tag)進行保留(reserved),以避免將來其它開發者不消息使用了刪除字段的數字。
  4. 對於數據類型的變化,例如int32到int64,string到bytes等等,能夠參考官方文檔:
    https://developers.google.com/protocol-buffers/docs/proto3#updating。 可是建議仍是儘可能不要去修改字段的數據類型。
 

添加字段

原來的proto是這樣的:
 
而後我添加一個name字段:
 
而這時,若是把新的消息發送到舊的代碼的時候,舊代碼不知道2這個數字tag對應的是什麼,因此name這個字段就會被忽略掉。
反過來,若是咱們使用新的代碼讀取舊的數據,那麼就會找不到新的字段,這時候就會使用該字段類型的默認值(空字符串)。
因此,處理默認值的時候必定要很是的當心
 

對字段重命名

如今我把name這個字段的名改爲了full_name,而它的數字不變:
這樣作是沒有任何問題的。
你能夠隨意改變字段的名字,只要它的數字tag不變就行,由於Protocol Buffer裏面這個數字tag纔是最重要的。
 

刪除字段

如今我又把full_name字段刪除了:
這時候,若是舊的代碼找不到這個字段了,那麼就會採用默認值。
反過來,若是咱們使用新的代碼讀取舊的數據,那麼已刪除的字段將會被忽略/丟棄。
 
可是,在刪除字段的時候,你應該一直都保留字段的數字tag以及字段名,像這樣:
這樣作是防止數字tag和名稱被重複使用,避免在之後的代碼庫裏形成衝突。
 

使用OBSOLETE

以前說了,能夠把字段名改成 OBSOLETE_字段名 來代替刪除字段,可是這樣作的缺點就是:你仍是須要把這個字段的值計算出來。我仍是建議使用reserve的方式進行刪除字段的管理。
 

Reserved

  • 你能夠保留字段的數字tag和字段名;
  • 可是不能夠在同一行語句裏混合reserved數字tag和字段名,應該分紅兩個語句:
 
  • 保留字段數字tag的目的就是防止數字tag被重複使用;
  • 而保留字段名的目的就是防止出現一些程序bug;
注意:必定不要移除reserved的數字tags。
 

默認值

默認值在更新Protocol Buffer消息定義的時候有很重要的做用,它能夠防止對現有代碼/新代碼形成破壞性影響。它們也能夠保證字段永遠不會有null值。
可是,默認值仍是很是危險的:
  • 你沒法區分這個默認值究竟是來自一個丟失的字段仍是字段的實際值正好等於默認值。
那麼應該怎麼辦?
  • 須要保證這個默認值對於業務來講是一個毫無心義的值。例如 int32 pop(人口)默認值就能夠設置爲-1。
  • 再就是,可能須要在你的代碼裏來作一些對默認值的判斷,從而進行處理。
 

枚舉

enum一樣能夠進化,就和消息的字段同樣,能夠添加、刪除值,也能夠保留值。
可是若是代碼不知道它接收到的值對應哪一個enum值,那麼enum的默認值將會被採用。
例如這個enum:
若是程序代碼接收到了5這個數值,那麼它找不到對應的枚舉值,因此就會使用這個枚舉的默認值0(UNSPECIFIED)。
相關文章
相關標籤/搜索