文章出處

最近開發的一個項目,后端采用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對應的類名可以放心大膽的修改。 


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()