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对应的类名可以放心大胆的修改。

时间: 2024-10-06 14:59:45

thrift 一个有意思的特性:Class名称无关性的相关文章

linux下一个有意思的问题(文件名以短划线或空格开头)

linux下一个有意思的问题(文件名以短划线开头) 这本是无意中的一个发现. 在linux下,文件名中含有 - 是没有问题,但是如果文件名是以-作为第一个字符的,那么就比较麻烦了. 问题演示 看这里,以短划线开头的文件名似乎对mv cp  rm   等操作免疫了.利用这个特性可以制造出一些比较麻烦的文件或者文件夹来. [email protected]:~$ ls -python.md [email protected]-pc:~$ mv -python.md 5-python.md mv:无效

一个有意思的需求——中文匹配度

引言 最近LZ带头在做一个互联网项目,互联网的东西总是那么新鲜,这也难怪大部分猿友都喜欢互联网.这个互联网项目不仅让LZ开发了一个HBase大数据应用,近期的一次需求讨论会上,又出来一个小需求,蛮有意思的.这些需求在之前枯燥的企业内部应用开发中,还是很难见到的,毕竟内部应用更多的是业务流程的体现. 具体的需求这里不方便透露,但简单的描述一下需求,就是如何判断两个公司名是一个.这其实就是Java当中字符串的相等判断,最简单的当然是用equals来判断.但是由于实际情况是,公司名是由客户手动输出的,

利用反射获取一个类实例的所有属性名称和值 拼接为字符串

需要一个功能:获取一个类实例的所有属性名称和值并拼接为字符串,然后进行处理.代码保存在此以备后用. 建立一个类文件ClassToString.cs 以下代码可以直接使用,参数为一个类的实例,返回的是一个数组,[0]为属性名的拼接,[1]为属性Value的拼接. 对于类的属性类型没有限制,但是如果没有全部赋值的话,Value会范围默认值, 比如int为0,String为空,DateTime为0001/1/1 0:00:00,0,0,0 需要有需要的话可以在拼接的时候判断进行相应处理 ClassTo

做一个有意思的人

http://www.nowamagic.net/librarys/eight/posts/2545到底应该过一个有意义的人生,还是做一个有意思的人?什么样的人才是一个有意思的人.第一次读这篇文章,我就十分感概.我们从小受教育说要为社会做贡献,上班了被要求以公司为家,或许我们应该思考一下如何做一个有意思的人.这篇文章或许你看过,我觉得可以再看一遍. 作者:黄铁鹰 & 芮成钢 与几位好友们有一个共识:大家对一个人最高的评价是:“这是一个很有意思,很精彩的人”.大家以这个标准,来判断一个人是否值得成

CSAPP中一个有意思的小东西

回家的效率明显下降了,但是第三章还是快要结束的节奏.今天看到定长数组这里的时候,看到一个好玩的东西.在计算机的底层中,所有对数组的操作都是利用指针来完成的.数组其实也是一个很简单的数据结构,就是把一些最简单的数据类型合并在一段连续的内存区域上,这就是一个复合类型---数组. 学C语言的时候,大家都知道访问数组元素有两种方法,一种是利用数组名加索引的形式,另外一种就是利用指针加上偏移量的形式.在底层中,不管你用什么方式来访问元素,最后多会转化成对指针的操作. 在编写 代码的时候,编译器在编译过程中

PHP框架Swoole的一个定时器Timer特性

在各种业务型系统中,往往需要服务器在后台扫描相关数据,触发相应的统计.通知等操作. 比如对于一个项目管理系统,需要每天的特定时间内,统计每项任务的执行.到期情况.整个项目的进度等等,根据统计情况,做相应通知处理: 这样一个场景,如何编程实现? 用一般的编程方式,是无法实现自动触发与统计的.当然,简单的思路,是利于系统的cron job机制.但这种方式,对于配置及可靠性方面,需要比较多的人为操作因素. Swoole是一个使用c开发的php扩展,通过php就可以实现高性能web服务器,同时,还内置了

Python一个有意思的地方:reduce、map、filter

今天阅读了关于Python函数式编程的系列文章,地址在这里: http://www.cnblogs.com/huxi/archive/2011/06/24/2089358.html 里面提到了四个内建迭代函数:reduce.map.filter.zip.其中zip是供同时迭代多个迭代器用的,这里就不讨论了.主要讨论剩下的三个. 我发现一个有意思的事情,就是剩下的三个函数,reduce.map和filter,三者可以相互转换.例如以reduce为基础,可以实现map和filter函数如下: 1 d

一个有意思的类扩展 有效解决判空问题

public static class ClassExtensions { public static TResult GetProperty<TClass, TResult>(this TClass obj, Func<TClass, TResult> func) where TClass : class { if ((object) obj == null) return default (TResult); else return func(obj); } public st

C#判断一个类中有无&quot;指定名称&quot;的方法

C#中可以通过反射分析元数据来解决这个问题,示例代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 using System; using System.Reflection; namespace Hello {     class Program     {