精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

聊聊為什么 IDL 只能擴展字段而非修改

大數據 數據分析
本文聊聊 grpc proto 變更時的兼容問題,核心只有一條:對擴展開放,對修改關閉,永遠只增加字段而不修改。

[[439484]]

本文轉載自微信公眾號「董澤潤的技術筆記」,作者董澤潤  。轉載本文請聯系董澤潤的技術筆記公眾號。

前幾年業界流行使用 thrift, 比如滴滴。這幾年 grpc 越來越流行,很多開源框架也集成了,我司大部分服務都同時開放 grpc 和 http 接口

相比于傳統的 http1 + json 組合,這兩種技術都用到了 IDL, 即 Interface description language 接口描述語言,相當于增加了 endpoint schema 約束,不同語言只需要一份相同的 IDL 文件即可生成接口代碼。

很多人喜歡問:proto buf 與 json 比起來有哪些優勢?比較經典的面試題

IDL 文件管理每個公司不一樣,有的保存在單獨 gitlab 庫,有的是 mono repo 大倉庫。當業務變更時,IDL 文件經常需要修改,很多新手總是容易踩坑,本文聊聊 grpc proto 變更時的兼容問題,核心只有一條:對擴展開放,對修改關閉,永遠只增加字段而不修改

測試修改兼容性

本文測試使用 grpc-go example 官方用例,感興趣自查

  1. syntax = "proto3"
  2.  
  3. option go_package = "google.golang.org/grpc/examples/helloworld/helloworld"
  4. package helloworld; 
  5.  
  6. // The greeting service definition. 
  7. service Greeter { 
  8.   // Sends a greeting 
  9.   rpc SayHello (HelloRequest) returns (HelloReply) {} 
  10.  
  11. // The request message containing the user's name
  12. message HelloRequest { 
  13.   string name = 1; 
  14.  
  15. // The response message containing the greetings 
  16. message HelloReply { 
  17.   string message = 1; 
  18.   string additional = 2; 
  19.   int32 age = 3; 
  20.   int64 id = 4; 

每次修改后使用 protoc 重新生成代碼

  1. protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative helloworld/helloworld.proto 

Server 每次接受請求后,返回 HelloReply 結構體

  1. // SayHello implements helloworld.GreeterServer 
  2. func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) { 
  3.  log.Printf("Received: %v"in.GetName()) 
  4.  return &pb.HelloReply{ 
  5.   Message:    "Hello addidional " + in.GetName(), 
  6.   Additional: "this is addidional field"
  7.   Age:        10, 
  8.   Id:         12345, 
  9.  }, nil 

Client 每次只打印 Server 返回的結果

修改字段編號

將 HelloReply 結構體字段 age 編號變成 12, 然后 server 使用新生成的 IDL 庫,client 使用舊版本

  1. zerun.dong$ ./greeter_client 
  2. ...... 
  3. 2021/12/08 22:23:38 Greeting: { 
  4.  "message""Hello addidional world"
  5.  "additional""this is addidional field"
  6.  "id": 12345 

可以看到 client 沒有讀到 age 字段,因為 IDL 是根據序號傳輸的,client 讀不到 seq 3, 所以修改序號不兼容

修改字段 name

修改 HelloReploy 字段 id, 變成 score 類型和序號不變

  1. // The response message containing the greetings 
  2. message HelloReply { 
  3.   string message = 1; 
  4.   string additional = 2; 
  5.   int32 age = 3; 
  6.   int64 score = 4; 

重新編譯 server, 并用舊版本 client 訪問

  1. zerun.dong$ ./greeter_client 
  2. ...... 
  3. 2021/12/08 22:29:18 Greeting: { 
  4.  "message""Hello addidional world"
  5.  "additional""this is addidional field"
  6.  "age": 10, 
  7.  "id": 12345 

可以看到,雖然修改了字段名,但是 client 仍然讀到了正確的值 12345, 如果字段含義不變,那么只修改名稱是兼容的

修改類型

有些類型是兼容的,有些不可以,而且還要考慮不同的語言。這里測試三種

1.字符串與字節數組

  1. // The response message containing the greetings 
  2. message HelloReply { 
  3.   string message = 1; 
  4.   bytes additional = 2; 
  5.   int32 age = 3; 
  6.   int64 id = 4; 

我們將 additional 字段由 string 類型修改為 bytes

  1. // The response message containing the greetings 
  2. type HelloReply struct { 
  3.  Message    string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"
  4.  Additional []byte `protobuf:"bytes,2,opt,name=additional,proto3" json:"additional,omitempty"
  5.  Age        int32  `protobuf:"varint,3,opt,name=age,proto3" json:"age,omitempty"
  6.  Id         int64  `protobuf:"varint,4,opt,name=id,proto3" json:"id,omitempty"

可以看到 go 結構體由 string 變成了 []byte, 我們知道這兩個其實可以互換

  1. zerun.dong$ ./greeter_client 
  2. ...... 
  3. 2021/12/08 22:35:43 Greeting: { 
  4.  "message""Hello addidional world"
  5.  "additional""this is addidional field"
  6.  "age": 10, 
  7.  "id": 12345 

最后結果也證明 client 可以正確的處理數據,即修改成兼容類型沒有任何問題

2.int32 int64 互轉

  1. message HelloReply { 
  2.   string message = 1; 
  3.   string additional = 2; 
  4.   int64 age = 3; 
  5.   int64 id = 4; 

這里我們將 age 由 int32 修改成 int64 字段,位數不一樣,如果同樣小于 int32 最大值沒有問題,此時我們在 server 端將 age 賦于 2147483647 + 1 剛好超過最大值

  1. zerun.dong$ ./greeter_client 
  2. ...... 
  3. 2021/12/08 22:43:32 Greeting: { 
  4.  "message""Hello addidional world"
  5.  "additional""this is addidional field"
  6.  "age": -2147483648, 
  7.  "id": 12345 

我們可以看到 age 變成了負數,如果業務剛好允許負值,那么此時一定會出邏輯問題,而且難以排查 bug, 這其實是非常典型的向上向下兼容問題

3.非兼容類型互轉

  1. message HelloReply { 
  2.   string message = 1; 
  3.   string additional = 2; 
  4.   string age = 3; 
  5.   int64 id = 4; 

我們將 age 由 int32 變成 string 字符串,依舊使用 client 舊版本測試

  1. zerun.dong$ ./greeter_client 
  2. ...... 
  3. 2021/12/08 22:55:21 Greeting: { 
  4.  "message""Hello addidional world"
  5.  "additional""this is addidional field"
  6.  "id": 12345 
  7. 2021/12/08 22:55:21 message:"Hello addidional world" additional:"this is addidional field" id:12345 3:"this is age" 
  8. 2021/12/08 22:57:56 r.Age is 0 

可以看到結構體 json 序列化打印時不存在 Age 字段,但是 log 打印時發現了不兼容的 3:"this is age", 注意 grpc 會保留不兼容的數據

同時 r.Age 默認是 0 值,即非兼容類型修改是有問題的

刪除字段

  1. message HelloReply { 
  2.   string message = 1; 
  3.   string additional = 2; 
  4.   // string age = 3; 
  5.   int64 id = 4; 

刪除字段 age 也就是說序號此時有空洞,運行 client 舊版本協義

  1. zerun.dong$ ./greeter_client 
  2. ...... 
  3. 2021/12/08 23:02:12 Greeting: { 
  4.  "message""Hello addidional world"
  5.  "additional""this is addidional field"
  6.  "id": 12345 
  7. 2021/12/08 23:02:12 message:"Hello addidional world"  additional:"this is addidional field"  id:12345 
  8. 2021/12/08 23:02:12 0 

沒有問題,打印 r.Age 當然是默認值 0, 即刪除字段是兼容的

為什么 required 在 proto3 中取消了?

  1. message SearchRequest { 
  2.   required string query = 1; 
  3.   optional int32 page_number = 2; 
  4.   optional int32 result_per_page = 3; 

熟悉 thrift 或是使用 proto2 協議的都習慣使用 required optional 來定義字段屬于,擴展字段一般標記為 optional, 必傳字段使用 required 來約束

官方解釋如下 issues2497[1],簡單說就是 required 打破了更新 IDL 時的兼容性

  • 永遠不能安全地向 proto 定義添加 required 字段,也不能安全地刪除現有的 required 字段,因為這兩個操作都會破壞兼容性
  • 在一個復雜的系統中,proto 定義在系統的許多不同組件中廣泛共享,添加/刪除 required 字段可以輕松地降低系統的多個部分
  • 多次看到由此造成的生產問題,并且 Google 內部幾乎禁止任何人添加/刪除 required 字段

上面是谷歌得出的結論,大家可以借鑒一下,但也不能唯 G 家論

小結

IDL 修改還有很多測試用例,感興趣的可以多玩玩,比如結構體間的轉換問題,比如 enum 枚舉類型。上文測試的都是 server 端使用新協義,client 使用舊協義,如果反過來呢?想測試 thrift 的可以看看這篇 thrift missing guide[2]

 

本文能過測試 case 想告訴大家,IDL 只能追加杜絕修改 (產品測試階段隨變改,無所謂)

 

責任編輯:武曉燕 來源: 董澤潤的技術筆記
相關推薦

2022-12-26 00:00:03

非繼承關系JDK

2022-05-17 22:20:41

哨兵Redis機制

2022-05-11 08:22:54

IO負載NFSOS

2012-03-06 20:51:04

iOS

2025-10-10 01:00:00

2022-02-21 07:54:28

單元測試編程開發

2024-01-30 07:55:03

KubernetesAPI服務器

2022-01-19 22:51:57

設計匿名用戶

2015-08-27 16:48:11

FirefoxChrome

2022-03-28 08:24:52

MySQL聚簇索引非聚簇索引

2017-02-10 09:55:53

SwiftObjective-C

2024-09-24 08:18:13

2021-11-29 10:24:56

WasmEnvoy 負載均衡

2023-02-15 08:41:56

多層維表性能寬表

2017-04-17 11:50:13

51CTO 學院

2019-07-02 08:30:25

蘋果 iOS系統

2020-12-29 05:34:00

動態代理

2023-07-05 08:17:38

JDK動態代理接口

2018-12-29 15:41:41

阿里巴巴程序員serialVersi

2024-08-07 08:14:26

點贊
收藏

51CTO技術棧公眾號

在线免费观看成人网| 国产精品私拍pans大尺度在线| 制服下的诱惑暮生| 懂色av一区| 成人激情小说网站| 国产成人av在线播放| 国产极品视频在线观看| 伊人久久亚洲| 日本久久电影网| 免费看污污视频| 五月天久久久久久| 麻豆精品91| 久久影院资源网| 污网站免费观看| 久久久人成影片一区二区三区在哪下载 | 亚洲资源一区| 国产99久久久国产精品潘金| 日本精品免费观看| 麻豆亚洲av熟女国产一区二| 久草成人在线| 日韩西西人体444www| 国产资源在线免费观看| 国产特黄在线| 粉嫩欧美一区二区三区高清影视| 国产精品扒开腿做爽爽爽视频| 欧美精品videos极品| 欧美一级精品片在线看| 精品成人一区二区| 日韩精品aaa| 亚洲成人人体| 午夜国产精品一区| 日韩欧美视频免费在线观看| 二区三区在线播放| av一区二区三区在线| 3d蒂法精品啪啪一区二区免费| 在线观看亚洲黄色| 噜噜噜91成人网| 久久久久久久久爱| 男女做暖暖视频| 久久激情电影| 亚洲午夜精品久久久久久性色 | 成人激情自拍| 6080国产精品一区二区| 尤蜜粉嫩av国产一区二区三区| www.日韩| 精品免费在线观看| 国产av熟女一区二区三区 | 一个色免费成人影院| 亚洲第一精品夜夜躁人人爽| 午夜性福利视频| 福利一区三区| 制服丝袜中文字幕一区| 五月婷婷激情久久| 青青热久免费精品视频在线18| 午夜精品久久久久影视| 老子影院午夜伦不卡大全| 日韩免费影院| 亚洲一区二区三区视频在线播放| 国产一级大片免费看| 国产三区在线观看| 日韩毛片在线免费观看| 正在播放久久| 国产cdts系列另类在线观看| 1000部国产精品成人观看| 亚洲精品欧美精品| 91精彩在线视频| 国产精品美女久久久久aⅴ | 亚洲一区二区三区四区五区六区| 澳门久久精品| 日韩av综合网站| 无码国产69精品久久久久同性| 美女亚洲一区| 一区二区三区亚洲| 久久福利免费视频| 中文字幕免费一区二区| 欧美激情在线视频二区| 天天综合网入口| 羞羞答答国产精品www一本| 日韩av免费在线播放| 中文字幕人妻精品一区| 极品少妇一区二区三区精品视频| 99久久精品久久久久久ai换脸| 国产自产一区二区| 91小视频在线| 日韩片电影在线免费观看| 欧美激情办公室videoshd| 亚洲色图清纯唯美| 久久国产精品视频在线观看| 国产精品伦理| 欧美精品一二三四| 极品白嫩少妇无套内谢| 日韩欧美国产大片| 精品国产区一区二区三区在线观看| 69av.com| 久久综合五月| 亚洲一区亚洲二区| 免费福利在线观看| 亚洲久草在线视频| 91av资源网| 亚洲精品第一| 亚洲大胆人体视频| 国产成人免费观看网站| 国产精品99一区二区| 国产成人高清激情视频在线观看 | 韩国欧美国产1区| 国产成人精品免费视频大全最热 | 欧美极品xxx| 喜爱夜蒲2在线| 免费成人动漫| 日韩美女视频在线| 国产传媒在线看| 亚洲三级色网| 91日本在线观看| 九色视频在线播放| 亚洲一区二区三区四区在线| 成人性生生活性生交12| aiss精品大尺度系列| 这里只有精品丝袜| 国产成人精品一区二三区| 久久se精品一区精品二区| 精品卡一卡二| 18加网站在线| 欧美婷婷六月丁香综合色| 国产精品一区二区人妻喷水| 99视频精品全国免费| 欧美主播福利视频| 日本久久一级片| 亚洲男人的天堂在线aⅴ视频| caoporn超碰97| 国产精品tv| 超在线视频97| 国产精品国产一区二区三区四区 | 亚洲а∨天堂久久精品9966| 无码人中文字幕| 久久久人人人| 激情五月综合色婷婷一区二区| 最新av在线播放| 欧美剧在线免费观看网站| 第一次破处视频| 中日韩视频在线观看| 不卡视频一区二区| 国产三区在线观看| 欧美高清视频一二三区| 国产白丝一区二区三区| 日韩电影免费在线看| 欧美日韩亚洲免费| 自由日本语热亚洲人| 亚洲精品久久久久久久久久久久 | 90岁老太婆乱淫| 99精品国产99久久久久久福利| 国产精品乱子乱xxxx| 色呦呦在线免费观看| 日韩欧美色综合| 中文字幕在线有码| 国产成人日日夜夜| www.国产亚洲| 国产+成+人+亚洲欧洲在线| 欧美成人全部免费| www.色呦呦| 亚洲一区在线视频观看| 免费啪视频在线观看| 亚洲高清自拍| 精品国产乱码一区二区三区四区| 精品三级久久| 亚洲人成电影在线播放| 糖心vlog精品一区二区| 国产精品久久久久7777按摩| 天堂在线一区二区三区| 欧美成人tv| 精品伊人久久大线蕉色首页| 天堂中文在线播放| 国产亚洲精品久久久久久777| 在线观看xxxx| 亚洲欧洲综合另类| 91精品啪在线观看国产| 欧美亚洲专区| 一区二区三区欧美成人| 国产美女视频一区二区| 午夜精品久久久久久久99热| 日韩一二三四| 欧美日韩亚洲高清一区二区| 国产探花在线视频| 粉嫩av一区二区三区粉嫩 | 蜜桃视频在线网站| 亚洲欧洲自拍偷拍| 国产精品无码白浆高潮| 亚洲国产乱码最新视频| 波多野结衣a v在线| 另类欧美日韩国产在线| 韩国无码av片在线观看网站| 亚洲欧洲色图| 91麻豆国产精品| 理论不卡电影大全神| 中文字幕一精品亚洲无线一区 | 亚洲天堂av在线免费| 亚洲一级av毛片| 亚洲国产色一区| 日本少妇xxxxx| 国产成人啪午夜精品网站男同| 漂亮人妻被中出中文字幕| 国产精品久久久久久麻豆一区软件 | 欧美日韩电影一区| 欧美日韩在线国产| 国产欧美日韩中文久久| 国产吃瓜黑料一区二区| 老牛国产精品一区的观看方式| 亚洲成人自拍| 国产成人夜色高潮福利影视| 国产精品久久久精品| 免费毛片在线看片免费丝瓜视频| 国产亚洲精品美女| 手机看片国产1024| 欧美日韩国产色站一区二区三区| 亚洲精品午夜久久久久久久| 国产精品久久久久aaaa| 一卡二卡三卡四卡| 成人丝袜18视频在线观看| 玖玖爱视频在线| 香蕉av777xxx色综合一区| 97超碰在线视| 欧美3p视频| 欧美日韩一区在线观看视频| 国产精东传媒成人av电影| 91久久久久久久| 国产精品99久久久久久董美香| 国语自产精品视频在线看| 国内精品久久久久国产| 一区二区三区回区在观看免费视频| 免费av一级片| 欧美成人乱码一区二区三区| 91好色先生tv| 在线观看视频91| 久久久久久少妇| 亚洲第一av色| 免费中文字幕在线观看| 国产精品免费久久| 中文字幕黄色网址| 久久久无码精品亚洲日韩按摩| 性色av蜜臀av浪潮av老女人| 国产不卡视频一区| 亚洲精品成人无码毛片| 国产精品夜夜嗨| 免费黄频在线观看| 精品一区二区三区在线播放视频 | 精品少妇久久久| 亚洲青青青在线视频| 三级在线观看免费大全| 中文字幕人成不卡一区| 亚洲色图27p| 国产精品你懂的| 成人信息集中地| 中文字幕一区二区三区不卡| 精品熟妇无码av免费久久| 国产精品三级在线观看| 奇米网一区二区| 亚洲婷婷综合久久一本伊一区| 欧美日韩色视频| 亚洲男人的天堂av| 久操免费在线视频| 亚洲福利视频导航| 在线观看亚洲天堂| 精品久久久久人成 | 欧美精品高清视频| 一区二区三区免费在线| 欧美美女激情18p| 国产ts人妖调教重口男| 日韩免费高清av| 日本高清视频网站| 日韩大片在线观看视频| 好男人免费精品视频| 色yeye香蕉凹凸一区二区av| 国产丝袜在线| 久久久久久久激情视频| 中文在线中文资源| 国产精品入口免费视| 狂野欧美xxxx韩国少妇| 国产精品入口免费| 久久99国产成人小视频| 一本久道久久综合| 国自产拍偷拍福利精品免费一| 欧美啪啪免费视频| 日韩成人伦理电影在线观看| 国产亚洲视频一区| 波多野结衣亚洲一区| 午夜精产品一区二区在线观看的| 中文字幕在线一区二区三区| 九九视频在线免费观看| 欧美午夜影院在线视频| 一区二区视频免费| 亚洲电影免费观看高清完整版在线| 九色视频成人自拍| 久久成人在线视频| 蜜桃视频m3u8在线观看| 成人免费观看a| 欧美久久精品| 日韩精品福利视频| 中文字幕av亚洲精品一部二部| 国产极品在线视频| 国内精品伊人久久久久av影院| 日本天堂在线播放| 国产精品理论在线观看| 日韩成人在线免费视频| 欧美久久久久免费| 四虎影视2018在线播放alocalhost| 中文字幕亚洲自拍| 欧美gv在线| 亚洲伊人一本大道中文字幕| 欧美女优在线视频| 成人免费在线视频播放| 日本欧美一区二区在线观看| 精品久久久久久无码人妻| 欧美国产欧美综合| av资源免费观看| 日韩一区二区免费在线电影| 国产特黄在线| 欧美性在线观看| www.神马久久| 桥本有菜av在线| 日韩精品免费专区| 少妇一级淫片免费放播放| 亚洲欧洲制服丝袜| 在线观看视频二区| 国产一区二区三区精品久久久 | 国产精品高清网站| 成人av影音| www国产无套内射com| 精品影视av免费| 超碰人人干人人| 色婷婷av一区二区三区之一色屋| 欧洲精品久久一区二区| 久国内精品在线| а天堂中文最新一区二区三区| 日韩欧美一区二区视频在线播放| 亚洲综合社区| 国产黄色三级网站| 亚洲一区二区三区激情| a级片免费观看| 日韩视频在线免费| 国模私拍国内精品国内av| 日韩精品资源| 石原莉奈一区二区三区在线观看| 影音先锋人妻啪啪av资源网站| 夜夜嗨av一区二区三区中文字幕 | 国产精品久久亚洲不卡| 美女一区视频| 久久国产日韩| 波多野结衣 在线| 欧美性猛交丰臀xxxxx网站| 色一情一乱一区二区三区| 性欧美在线看片a免费观看| 国产厕拍一区| 欧美日韩成人免费视频| av一区二区久久| 在线观看亚洲欧美| 亚洲欧美日韩久久久久久| 久久青青视频| 日韩福利影院| 看国产成人h片视频| 999精品视频在线观看播放| 欧美麻豆精品久久久久久| 成码无人av片在线观看网站| 成人在线看片| 国产欧美日本| 在线免费观看视频| 欧美日韩一级二级三级| 欧美成人hd| 99免费在线观看视频| 亚洲国内欧美| 国产精品无码久久久久一区二区| 色婷婷av一区二区三区大白胸| 国产九九在线| 成人欧美一区二区三区黑人孕妇 | 久久9精品区-无套内射无码| 久久久久久久久久看片| 亚洲午夜精品久久久| 久久99国产精品自在自在app| 99久久免费精品国产72精品九九| 大陆极品少妇内射aaaaa| 国产片一区二区三区| 国产精品一区二区免费视频 | 久久97人妻无码一区二区三区| 精品久久人人做人人爽| 日韩成人影音| 一区二区三区一级片| 成人av在线一区二区| 精品人妻一区二区三区潮喷在线| 色一情一乱一区二区| 一区中文字幕| 国产无套粉嫩白浆内谢的出处| 亚洲三级电影全部在线观看高清| 国模人体一区二区| 国产精品aaa| 欧美久色视频| 高潮毛片无遮挡| 日韩一区二区在线观看| 人人鲁人人莫人人爱精品| 国产 国语对白 露脸| 国产亚洲成aⅴ人片在线观看| 国产手机视频在线| 热久久免费视频精品|