thrift是一个RPC框架,一般用于提供远程接口调用的,也就是作为服务器供其他的客户端调用,这个客户端也可以是指其他的服务器。比如很多电商后端会分为逻辑和服务器,把许多公用的模块作为一个服务来做,对外提供接口,供其他模块调用。
1.thrift的安装
https://thrift.apache.org/docs/BuildingFromSource
2 thrift的描述文件
thrift和protobuffer 类似,都提供了一种序列化方式,首先需要定义描述文件,thrift需要定义.thrift文件。格式类似于:
struct Info {
1:requred i32 uid,
2:optional i32 age,
}
service nameserver {
i32 getAge(1:i32 uid);
}
以上代码中 i32表示int32位即四个字节,此外还有 i64 Info 为自定义类型。 required 表示该字段必须被赋值,optional则表示可有可无。service表示 提供的服务模块,里面定义对外接口。1:i32 uid 表示第一个参数是int 参数名是uid,以此类推。该函数的返回值是i32位。
3具体使用
thrift支持很多种语言,包括C++/python/java/erlang/perl等。需要通过thrift的工具来生成具体的语言代码。
以C++为例(此外blade也支持thrift编译 ):
thrift --gen cpp test.thrift
会生成gen-cpp目录,目录下存放生成的文件,每个thrift文件会产生四个文件,分别为:
{thrift_name}_constants.h,{thrift_name}_constants.cpp,{thrift_name}_types.h,{thrift_name}_types.cpp######
对于含有service的thrift文件,会额外生成两个文件,分别为
{service_name}.h, {service_name}.cpp######
对于含有service的thrift文件,会生成一个可用的server桩:{service_name}._server.skeleton.cpp**
{thrift_name}_types是关于自定义的类型的具体实现。一般其他文件需要用到该类型,只需要引用头文件即可。
在使用自定义类型时,查看{thrift_name}_types.h会发现,
typedef struc _Info_isset {
_Info_isset():age(false) {}
bool age:1;
}_Info__isset;
_Info_isset __isset;
thrift为了区分required和optional,如果字段设为optional的话.Info会有一个成员变量__isset;里面的age为false表示Info.age未赋值,true表示赋值。自定义的字段默认成员属性都是public的,可以直接通过对象访问,但是对于optional的字段:
1)需要访问Info的属性信息,不能通过Info info; int b = info.age
需要先检测该字段是默认值,如果info.__isset.age = false,则就是默认值0.
2)如果要修改字段值,同样也不能直接使用 info.age = 25,需要info.__set_age()来修改,该函数里同样修改了info.__isset.age 的值。
thrift在序列化过程中回去检测标志位,如果不同__set_age()来修改,则传输过程中age的值会被丢弃恢复到默认值。