thrift 的required、optional探究
原因
经常使用thrift来编写rpc通信,但是对下面两个问题还是有些疑惑
- thrift 的required、optional和不写有什么区别
- optional不设置isset的话被传输后值?
实验
今天就自己编写代码测试了一下。如下:
定义book.thrift 如下:
1: namespace cpp codelab
2:
3: struct Book {
4: 1: i32 book_id
5: 2: string name
6: 3: optional string optional_attr,
7: 4: optional string optional_default_val_attr = "optional_default_val_attr",
8: 5: string default_attr,
9: 8: string default_val_attr = "default_val_attr",
10: 10: required string required_attr,
11: 11: required string required_default_val_attr = "equired_default_val_attr",
12: }
client代码如下:
1: int main(int argc, char **argv) {
2: boost::shared_ptr<TSocket> socket(new TSocket("localhost", 9090));
3: boost::shared_ptr<TTransport> transport(new TFramedTransport(socket));
4: boost::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
5:
6: HelloBookClient client(protocol);
7: transport->open();
8: Book book;
9: book.name = "hello thrift";
10: printf("book __isset.name: %d\n", book.__isset.name);
11: printf("book name: %s\n", book.name.c_str());
12: printf("book __isset.optional_attr: %d\n", book.__isset.optional_attr);
13: printf("book optional_attr: %s\n", book.optional_attr.c_str());
14: printf("book __isset.optional_default_val_attr: %d\n",
15: book.__isset.optional_default_val_attr);
16: printf("book optional_default_val_attr: %s\n",
17: book.optional_default_val_attr.c_str());
18: printf("book __isset.default_attr: %d\n", book.__isset.default_attr);
19: printf("book default_attr: %s\n", book.default_attr.c_str());
20: printf("book __isset.default_val_attr: %d\n",
21: book.__isset.default_val_attr);
22: printf("book default_val_attr: %s\n", book.default_val_attr.c_str());
23: // printf("book __isset.required_attr: %d\n",
24: // book.__isset.required_attr);
25: printf("book required_attr: %s\n", book.required_attr.c_str());
26: // printf("book __isset.required_default_val_attr: %d\n",
27: // book.__isset.required_default_val_attr);
28: printf("book required_default_val_attr: %s\n",
29: book.required_default_val_attr.c_str());
30:
31: client.ping(book);
32: transport->close();
33:
34: return 0;
35:
Server端代码:
1: class HelloBookHandler : virtual public HelloBookIf {
2: public:
3: HelloBookHandler() {
4: // Your initialization goes here
5: }
6:
7: void ping(const codelab::Book& book) {
8: // Your implementation goes here
9: printf("book __isset.name: %d\n", book.__isset.name);
10: printf("book name: %s\n", book.name.c_str());
11: printf("book __isset.optional_attr: %d\n", book.__isset.optional_attr);
12: printf("book optional_attr: %s\n", book.optional_attr.c_str());
13: printf("book __isset.optional_default_val_attr: %d\n",
14: book.__isset.optional_default_val_attr);
15: printf("book optional_default_val_attr: %s\n",
16: book.optional_default_val_attr.c_str());
17: printf("book __isset.default_attr: %d\n", book.__isset.default_attr);
18: printf("book default_attr: %s\n", book.default_attr.c_str());
19: printf("book __isset.default_val_attr: %d\n",
20: book.__isset.default_val_attr);
21: printf("book default_val_attr: %s\n", book.default_val_attr.c_str());
22: // printf("book __isset.required_attr: %d\n",
23: // book.__isset.required_attr);
24:
25: printf("book required_attr: %s\n", book.required_attr.c_str());
26: // printf("book __isset.required_default_val_attr: %d\n",
27: // book.__isset.required_default_val_attr);
28: printf("book required_default_val_attr: %s\n",
29: book.required_default_val_attr.c_str());
30: }
31: };
32:
33: int main(int argc, char **argv) {
34: int port = 9090;
35: boost::shared_ptr<HelloBookHandler> handler(new HelloBookHandler());
36: boost::shared_ptr<TProcessor> processor(new HelloBookProcessor(handler));
37: boost::shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
38: boost::shared_ptr<TTransportFactory> transportFactory(
39: new TFramedTransportFactory());
40: boost::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
41:
42: TSimpleServer server(processor, serverTransport,
43: transportFactory, protocolFactory);
44: server.serve();
45: return 0;
46: }
Client端执行结果:
Server端执行结果:
而对client代码修改如下,
server端的执行结果分别如下:
即没有设置isset为true的时候optional_attr的值到server被丢失了。而设置为true之后才能在server获取到
经过上面的测试,得到以下结论:
- required字段没有__isset属性, 而默认的(就是既没有required,也没有optional)和optional的属性有该方法。
- 创建对象的时候,optional和默认的__isset属性为false,同样不设置该属性,而在经过thrift rpc传输之后,server端的默认的__isset属性为true,而optional的__isset的属性为true。
- 有默认值的属性,不赋值的话,其值就是thrift中的默认值。
- optional的如果没有设置__isset为true,则经过rpc传输(或者说是经过序列化再反序列化)之后,其值会丢失。
为什么会有上面的结果呢:
原因分析
查看thrift生成的文件:
其中book_types.h 如下:
1: /**
2: * Autogenerated by Thrift
3: *
4: * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
5: */
6: #ifndef book_TYPES_H
7: #define book_TYPES_H
8:
9: #include <Thrift.h>
10: #include <TApplicationException.h>
11: #include <protocol/TProtocol.h>
12: #include <transport/TTransport.h>
13:
14:
15:
16: namespace codelab {
17:
18: typedef struct _Book__isset {
19: _Book__isset() : book_id(false), name(false), optional_attr(false), optional_default_val_attr(false), default_attr(false), default_val_attr(false) {}
20: bool book_id;
21: bool name;
22: bool optional_attr;
23: bool optional_default_val_attr;
24: bool default_attr;
25: bool default_val_attr;
26: } _Book__isset;
27:
28: class Book {
29: public:
30:
31: static const char* ascii_fingerprint; // = "EC22AAB82386E1FAA959FB075574467D";
32: static const uint8_t binary_fingerprint[16]; // = {0xEC,0x22,0xAA,0xB8,0x23,0x86,0xE1,0xFA,0xA9,0x59,0xFB,0x07,0x55,0x74,0x46,0x7D};
33:
34: Book() : book_id(0), name(""), optional_attr(""), optional_default_val_attr("optional_default_val_attr"), default_attr(""), default_val_attr("default_val_attr"), required_attr(""), required_default_val_attr("equired_default_val_attr") {
35: }
36:
37: virtual ~Book() throw() {}
38:
39: int32_t book_id;
40: std::string name;
41: std::string optional_attr;
42: std::string optional_default_val_attr;
43: std::string default_attr;
44: std::string default_val_attr;
45: std::string required_attr;
46: std::string required_default_val_attr;
47:
48: _Book__isset __isset;
49:
50: bool operator == (const Book & rhs) const
51: {
52: if (!(book_id == rhs.book_id))
53: return false;
54: if (!(name == rhs.name))
55: return false;
56: if (__isset.optional_attr != rhs.__isset.optional_attr)
57: return false;
58: else if (__isset.optional_attr && !(optional_attr == rhs.optional_attr))
59: return false;
60: if (__isset.optional_default_val_attr != rhs.__isset.optional_default_val_attr)
61: return false;
62: else if (__isset.optional_default_val_attr && !(optional_default_val_attr == rhs.optional_default_val_attr))
63: return false;
64: if (!(default_attr == rhs.default_attr))
65: return false;
66: if (!(default_val_attr == rhs.default_val_attr))
67: return false;
68: if (!(required_attr == rhs.required_attr))
69: return false;
70: if (!(required_default_val_attr == rhs.required_default_val_attr))
71: return false;
72: return true;
73: }
74: bool operator != (const Book &rhs) const {
75: return !(*this == rhs);
76: }
77:
78: bool operator < (const Book & ) const;
79:
80: uint32_t read(::apache::thrift::protocol::TProtocol* iprot);
81: uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const;
82:
83: };
84:
85: } // namespace
86:
87: #endif
book_types.cpp 文件如下:
1: /**
2: * Autogenerated by Thrift
3: *
4: * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
5: */
6: #include "codelab/thrift/proto/gen-cpp/book_types.h"
7:
8: namespace codelab {
9:
10: const char* Book::ascii_fingerprint = "EC22AAB82386E1FAA959FB075574467D";
11: const uint8_t Book::binary_fingerprint[16] = {0xEC,0x22,0xAA,0xB8,0x23,0x86,0xE1,0xFA,0xA9,0x59,0xFB,0x07,0x55,0x74,0x46,0x7D};
12:
13: uint32_t Book::read(::apache::thrift::protocol::TProtocol* iprot) {
14:
15: uint32_t xfer = 0;
16: std::string fname;
17: ::apache::thrift::protocol::TType ftype;
18: int16_t fid;
19:
20: xfer += iprot->readStructBegin(fname);
21:
22: using ::apache::thrift::protocol::TProtocolException;
23:
24: bool isset_required_attr = false;
25: bool isset_required_default_val_attr = false;
26:
27: while (true)
28: {
29: xfer += iprot->readFieldBegin(fname, ftype, fid);
30: if (ftype == ::apache::thrift::protocol::T_STOP) {
31: break;
32: }
33: switch (fid)
34: {
35: case 1:
36: if (ftype == ::apache::thrift::protocol::T_I32) {
37: xfer += iprot->readI32(this->book_id);
38: this->__isset.book_id = true;
39: } else {
40: xfer += iprot->skip(ftype);
41: }
42: break;
43: case 2:
44: if (ftype == ::apache::thrift::protocol::T_STRING) {
45: xfer += iprot->readString(this->name);
46: this->__isset.name = true;
47: } else {
48: xfer += iprot->skip(ftype);
49: }
50: break;
51: case 3:
52: if (ftype == ::apache::thrift::protocol::T_STRING) {
53: xfer += iprot->readString(this->optional_attr);
54: this->__isset.optional_attr = true;
55: } else {
56: xfer += iprot->skip(ftype);
57: }
58: break;
59: case 4:
60: if (ftype == ::apache::thrift::protocol::T_STRING) {
61: xfer += iprot->readString(this->optional_default_val_attr);
62: this->__isset.optional_default_val_attr = true;
63: } else {
64: xfer += iprot->skip(ftype);
65: }
66: break;
67: case 5:
68: if (ftype == ::apache::thrift::protocol::T_STRING) {
69: xfer += iprot->readString(this->default_attr);
70: this->__isset.default_attr = true;
71: } else {
72: xfer += iprot->skip(ftype);
73: }
74: break;
75: case 8:
76: if (ftype == ::apache::thrift::protocol::T_STRING) {
77: xfer += iprot->readString(this->default_val_attr);
78: this->__isset.default_val_attr = true;
79: } else {
80: xfer += iprot->skip(ftype);
81: }
82: break;
83: case 10:
84: if (ftype == ::apache::thrift::protocol::T_STRING) {
85: xfer += iprot->readString(this->required_attr);
86: isset_required_attr = true;
87: } else {
88: xfer += iprot->skip(ftype);
89: }
90: break;
91: case 11:
92: if (ftype == ::apache::thrift::protocol::T_STRING) {
93: xfer += iprot->readString(this->required_default_val_attr);
94: isset_required_default_val_attr = true;
95: } else {
96: xfer += iprot->skip(ftype);
97: }
98: break;
99: default:
100: xfer += iprot->skip(ftype);
101: break;
102: }
103: xfer += iprot->readFieldEnd();
104: }
105:
106: xfer += iprot->readStructEnd();
107:
108: if (!isset_required_attr)
109: throw TProtocolException(TProtocolException::INVALID_DATA);
110: if (!isset_required_default_val_attr)
111: throw TProtocolException(TProtocolException::INVALID_DATA);
112: return xfer;
113: }
114:
115: uint32_t Book::write(::apache::thrift::protocol::TProtocol* oprot) const {
116: uint32_t xfer = 0;
117: xfer += oprot->writeStructBegin("Book");
118: xfer += oprot->writeFieldBegin("book_id", ::apache::thrift::protocol::T_I32, 1);
119: xfer += oprot->writeI32(this->book_id);
120: xfer += oprot->writeFieldEnd();
121: xfer += oprot->writeFieldBegin("name", ::apache::thrift::protocol::T_STRING, 2);
122: xfer += oprot->writeString(this->name);
123: xfer += oprot->writeFieldEnd();
124: if (this->__isset.optional_attr) {
125: xfer += oprot->writeFieldBegin("optional_attr", ::apache::thrift::protocol::T_STRING, 3);
126: xfer += oprot->writeString(this->optional_attr);
127: xfer += oprot->writeFieldEnd();
128: }
129: if (this->__isset.optional_default_val_attr) {
130: xfer += oprot->writeFieldBegin("optional_default_val_attr", ::apache::thrift::protocol::T_STRING, 4);
131: xfer += oprot->writeString(this->optional_default_val_attr);
132: xfer += oprot->writeFieldEnd();
133: }
134: xfer += oprot->writeFieldBegin("default_attr", ::apache::thrift::protocol::T_STRING, 5);
135: xfer += oprot->writeString(this->default_attr);
136: xfer += oprot->writeFieldEnd();
137: xfer += oprot->writeFieldBegin("default_val_attr", ::apache::thrift::protocol::T_STRING, 8);
138: xfer += oprot->writeString(this->default_val_attr);
139: xfer += oprot->writeFieldEnd();
140: xfer += oprot->writeFieldBegin("required_attr", ::apache::thrift::protocol::T_STRING, 10);
141: xfer += oprot->writeString(this->required_attr);
142: xfer += oprot->writeFieldEnd();
143: xfer += oprot->writeFieldBegin("required_default_val_attr", ::apache::thrift::protocol::T_STRING, 11);
144: xfer += oprot->writeString(this->required_default_val_attr);
145: xfer += oprot->writeFieldEnd();
146: xfer += oprot->writeFieldStop();
147: xfer += oprot->writeStructEnd();
148: return xfer;
149: }
150:
151: } // namespace
thrift 的required、optional探究的更多相关文章
- Thrift中required和optional
最近在搞Thrift,对其字段声明中的required关键字有所误解,仔细调试了一下才明白其真实含义. required的意思不是说声明对象时,必须填这个值,而是Thrift在传输(序列化)过程中无论 ...
- How to fix the bug “Expected "required", "optional", or "repeated".”?
参考:https://github.com/tensorflow/models/issues/1834 You need to download protoc version 3.3 (already ...
- Thrift.0
0. Thrift的特性 1. 安装Thrift编译器 [Todo] http://thrift.apache.org/docs/install/ http://thrift.apache.org/d ...
- Netty学习——Thrift的入门使用
Netty学习——Thrift的入门使用 希望你能够,了解并使用它.因为它是一个效率很高的框架 官网地址:http://thrift.apache.org/ 1.Thrift数据类型 一门技术如果需要 ...
- Google 开源技术protobuf
http://blog.csdn.net/hguisu/article/details/20721109#0-tsina-1-1601-397232819ff9a47a7b7e80a40613cfe1 ...
- Potocol Buffer详解
protocol安装及使用 上一篇博文介绍了一个综合案例,这篇将详细介绍protocol buffer. 为什么使用protocol buffer? java默认序列化效率较低. apache的thr ...
- gRPC学习
概述 gRPC 一开始由 google 开发,是一款语言中立.平台中立.开源的远程过程调用(RPC)系统. 在 gRPC 里客户端应用可以像调用本地对象一样直接调用另一台不同的机器上服务端应用的方法, ...
- Storm Flow
A Stream represents the core data model in Trident, and can be thought of as a "stream" of ...
- iOS:以前笔记,未整理版。太多了,先放着吧。。。。。。。
1. -(void)timetick { _d = 0; NSTimer *newtime =[NSTimer scheduledTimerWithTimeInterval:1 target:self ...
随机推荐
- Codeforces 358D DP
题意:有n只兔子需要喂养,每只兔子被喂养后的幸福感取决于与它相邻的兔子中已经被喂养的数量.现在问喂养这n只兔子可以获得的总幸福感最多是多少? 思路:初步分析题目发现,一只兔子被喂养获得的幸福感取决于其 ...
- 六、SpringBoot配置@ConfigurationProperties与@Value区别
1.@Value的使用 三种用法 // ${key} 从环境变量.配置文件中取值 @Value("${person.last-name}") private String last ...
- 【串线篇】浅谈BeanFactory
BeanFactory&ApplicationContext BeanFactory: bean工厂接口,负责创建bean实例, 容器里保存的所有单例bean其实是一个map<key-- ...
- C++ 字符串截取转换及字符流控制
文章由来 ------------------工作需要缓冲区里的字符串控制,还是混合编译的那种,根据协议来定义截取各种字符流,控制大小长度,截取返回的内容然后转换成特定的类型, 可能表述不是那么正确, ...
- OpenCV常用基本处理函数(3)颜色空间
颜色空间转换 对图像进行颜色空间转换,比如从 BGR 到灰度图,或者从BGR 到 HSV 等 我们要用到的函数是:cv2.cvtColor(input_image ,flag),其中 flag就是转换 ...
- Python技能树
本博客Python内容的索引,以后就照着它写了.
- permutations and combinations
# import itertools # # my_list = [1, 2, 3, 4, 5, 6] # # combinations = itertools.combinations(my_lis ...
- SCP-bzoj-1079
项目编号:bzoj-1079 项目等级:Safe 项目描述: 戳这里 特殊收容措施: DP.普通的状压状态数515,显然TLE+MLE,我们考虑把底数和幂换一换,压成155的状态数. 故状态设计为:f ...
- Database基础(七):部署集群基础环境、MySQL-MMM架构部署、MySQL-MMM架构使用
一.部署集群基础环境 目标: 本案例要求为MySQL集群准备基础环境,完成以下任务操作: 数据库授权 部署MySQL双主多从结构 配置本机hosts解析记录 方案: 使用4台RHEL 6虚拟机,如下图 ...
- Python基础(二):斐波那契数列、模拟cp操作、生成8位随机密码
一.斐波那契数列 目标: 编写fib.py脚本,主要要求如下: 输出具有10个数字的斐波那契数列 使用for循环和range函数完成 改进程序,要求用户输入一个数字,可以生成用户需要长度的斐波那契数列 ...