实习中第一次帮助mentor之thrift协议
Thrift协议
前因后果
在实习中发现自己需要用thrift协议发送请求,起因就是需要用到公司内部rpc来进行服务之间的请求
本篇主要着重于如何解读thrift接口文档,节省大家的时间
thrift的优点
二进制格式:Thrift 使用二进制格式来序列化和反序列化数据,这使得它在网络传输中比纯文本格式的 HTTP 协议更高效,占用的带宽更少,不过相比http2这个优点就不大了
解读thrift接口文档
如何看懂?
- 找到service关键字(下面的Service包起来的内容就好比一个方法(有参数,有返回值)只不过统一定义了)
service LocService {
///< 批量根据坐标查cid,返回值顺序与输入坐标顺序一致 最多支持50个
DemoResponse AreaInfoByTest(1:CoordRequest req);
}
- 看参数(确定参数的结构体)
struct MultiCoordRequest {
3: required list<Coordinate> coords, // 请求坐标
4: required CoordType req_coord_type // 请求坐标的坐标类型
5: optional AreaFilter area_filter; // 裁剪返回城市信息,默认返回国家/地区,省、市的简要信息(不包含名称),默认返回本地语言
}
- 根据结构体设置参数,参数中可能还是结构体(这点与json或者yaml等文件类似,都以某种形式表达数组或list或者对象,可以去其他网站查,不赘叙)
- 看返回对象,同理如果有结构体,就看结构体(thrift的优点就在此,基本上每种语言都是一样的流程)
- 编写发送请求(这里要看各个公司的情况了,由于涉及公司具体内容所以不涉及,一般公司其实会写好SDK,给大家可以直接使用,或者搜索看已有项目是否有类似的rpc调用代码,或者就看对应的rpc的文档)
其他字段
namespace的意义
其实是thrift有自动生成代码的功能,所以在这里的作用以java为例,就是在seamount3.locs包下生成对应的代码
// location service服务
namespace cpp seamount3.locs
namespace java seamount3.locs
namespace go seamount3.locs
enum的意义
其实就是和java的一样,给你用来枚举的
enum Area_RET_TYPE {
AREA_ADMIN_SIMPLE = 1, //返回国家/地区,省、市的简要信息
AREA_ADMIN_DETAIL = 2 //返回国家/地区,省、市、区的简要信息
}
记一次thrift调用的BUG&&实习生生涯中第一次帮助到mentor(也不全是)
情况是:当时需要调用别人写好的rpc接口,mentor有自己的需求,所以调试接口的任务就由我来了,我对rpc的概念算地上理解,但是对于thrift协议其实完全不懂,mentor是先给我写了个解决方法,不过说是还没调试好,所以我就开始试错
语言:php
调试的过程直接借用了mentor调试的场景,直接echo了请求(公司是webIDE开发),但是echo回来的json数据,其实根据thrift的请求结构体应该是没有问题的,
"area_filter": {
"area_type": 2
}
但是只要一传area_filter就返回null,只是null(这里跳过了摸爬滚打改mentor请求参数的流程,最终得到和mentor原本一样的请求参数,但是结果显然还是不行),而且json返回的格式是正常的,是符合我预期的,但是就是获取不到数据
采取措施:
- 找对应服务值班人员看,发现值班人员那边是可以获取到数据的
那么问题在哪?
json欺骗了我?
最终的原因:
- php是弱类型语言,thrift是强类型协议
- 序列化机制的不同,json的序列化会直接将php的数组or map转成对象,而thrift不会,他是强类型,所以在序列化的过程中序列化出来的数据是无法正常反序列化的,所以对方服务才直接返回null
这还是本实习生,第一次帮助到了正式员工,于是有所感怀,故做此篇