thrift 一個有意思的特性:Class名稱無關性

TigerJin發表於2021-09-09

最近開發的一個專案,後端採用thrift框架來提供rpc服務(java語言實現),然後前端採用php語言來生成thrift client呼叫後臺RPC服務。由於某些原因,上週我把thrift定義檔案中一個struct名稱修改了,當然也沒多想,順手就把java服務端重新編譯部署,而php前端的部署未做任何變化,按常規理解,服務契約中的類名,從A改成B,服務的呼叫方理應同步更新部署,否則感覺應該會出錯。

然而,美好的事情就這麼發生了,一切執行正常,依舊絲絲順滑!

再然後,我就開始思考人生,重新理解 thrift內部的序列化與反序列化機制,很快就想明白了,借用之前寫過的部落格rpc框架之 avro 學習 2 - 高效的序列化中的一張圖:

圖片描述

 thrift內部儲存二進位制資料時,為了提高儲存效率,每個field都分配了一個數字編號,所以在序列化及反序列化時,其實是隻認數字編號,不管名稱的,這也正是thrift IDL檔案定義struct時,為什麼強制要求每個成員都要指定一個在struct本身範圍內不重複的數字序號

圖片描述

struct PersonModel {  1: i16 age = 0,  2: string name,  3: bool sex,  4: double salary,  5: byte childrenCount}

圖片描述

IDL生成的具體語言的原始碼中,解析物件時,同樣也只看序號,以c#生成的程式碼為例:

圖片描述

 1    public void Read (TProtocol iprot) 
 2     { 
 3       iprot.IncrementRecursionDepth(); 
 4       try 
 5       { 
 6         TField field; 
 7         iprot.ReadStructBegin(); 
 8         while (true) 
 9         {
 10           field = iprot.ReadFieldBegin();
 11           if (field.Type == TType.Stop) { 
 12             break;
 13           }
 14           switch (field.ID)
 15           {
 16             case 1:
 17               if (field.Type == TType.I16) {
 18
                  Age = iprot.ReadI16();
 19               } else { 
 20                 TProtocolUtil.Skip(iprot, field.Type);
 21               }
 22               break;
 23             case 2:
 24               if (field.Type == TType.String) {
 25                 Name = iprot.ReadString();
 26               } else { 
 27                 TProtocolUtil.Skip(iprot, field.Type);
 28               }
 29               break;
 30             case 3:
 31               if (field.Type == TType.Bool) {
 32                 Sex = iprot.ReadBool();
 33               } else { 
 34                 TProtocolUtil.Skip(iprot, field.Type);
 35               }
 36               break;
 37             case 4:
 38               if (field.Type == TType.Double) {
 39                 Salary = iprot.ReadDouble();
 40               } else { 
 41                 TProtocolUtil.Skip(iprot, field.Type);
 42               }
 43               break;
 44             case 5:
 45               if (field.Type == TType.Byte) {
 46                 ChildrenCount = iprot.ReadByte();
 47               } else { 
 48                 TProtocolUtil.Skip(iprot, field.Type);
 49               }
 50               break;
 51             default: 
 52               TProtocolUtil.Skip(iprot, field.Type);
 53               break;
 54           }
 55           iprot.ReadFieldEnd();
 56         }
 57         iprot.ReadStructEnd();
 58       }
 59       finally
 60       {
 61         iprot.DecrementRecursionDepth();
 62       }
 63     }

圖片描述

從上面的case語句可以很清楚的看出,程式碼內部只認數字序號,不關心名稱。

 

結論:只要不改變struct內部的成員型別和數字編號,struct對應的類名可以放心大膽的修改。 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2144/viewspace-2801334/,如需轉載,請註明出處,否則將追究法律責任。

相關文章