• thrift 一个有意思的特性:Class名称无关性


    最近开发的一个项目,后端采用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对应的类名可以放心大胆的修改。 

  • 相关阅读:
    连续子数组的最大和
    孩子们的游戏(圆圈中最后剩下的数)
    左旋转字符串
    业界难题-“跨库分页”的四种方案
    InnoDB意向锁的作用
    Linux下Fork与Exec使用
    minixml的安装教程
    main()函数的形参
    结构体数组初始化
    fork函数详解
  • 原文地址:https://www.cnblogs.com/yjmyzz/p/thrift-classname-independent.html
Copyright © 2020-2023  润新知