Thrift RPC Erlang库大量数据时出错的解决

Kate ·
更新时间:2024-09-21
· 760 次阅读

我们项目的各个server之间是使用thrift rpc库来互相rpc的,我们使用的版本是0.9.2, 我制定了统一的消息格式,控制和包装好整个rpc的使用方法,来方便我们服务端的开发人员来使用,一开始因为rpc的数据量很少,所以基本没啥问题, 最近项目有一个大的rpc数据,开发反映rpc库报错,报错如下(用测试的demo工程来再现):

是typeid_to_atom()的参数匹配‘:'出了错,这就奇怪了,减少rpc数据请求量,又正常,在确认使用方法没有问题后,想到的是rpc参数是不是有哪个默认参数有问题,开始想到buffer不够大,去看buffer大小的限制,发现是一个list,这样就没有限制,排除这个原因。 再怀疑是recv timeout太短,默认是60秒,也排除。其它每一个参数都认真检查发现都没问题,这就怪了,这算是一个比较出名的库,应该不会代码有这么明显示的bug没测出来吧,参数反复检查没问题后,只能硬着头皮去看库的代码,花了一天时间,梳理了代码,整条线基本是这样:thrift_client:receive_function_result --> read_result --> handle_reply --> thrift_protocol:read --> read_specific -> thrift_protocol_binary:read -->read_data --> thrift_buffer_transport:read --> thrift_socket_transport:read --> recv.这是接收数据的一条线,thrift_protocol里的read调用read_struct_loop,这里是循环读数据的:

这个函数里的read(IProto1, Type)是读数据,但是奇怪的是下面紧接着读这个field_end,也就是说这个read要把数据全部读完,才是完整的数据,进一步读这个read,到了thrift_binary_protocol模块的:

因为我的返回值是string,所以我看这块的string,  读string时,前面4个字节是这个string的长度,先读出来,然后read_data这个长度的数据,ok,没有问题,再进一步进入到thrift_socket_transport里的read函数:

反复看了这一块的代码,发现了问题,如果buffer的数据不够,去recv,但是recv的长度小于我们需要的小度时,这里并没有做循环去recv,从这个现象,反推过去我们的报错正好是读到这个截断处的数据’:',一切问题都合对上了。接下来是怎么改的问题,两个方法:一种是在thrift_binary_protocol.erl的read string那里,判断返回的值的长度是不是 小于Sz,如果小于继续读;另一种方法是thrift_socket_transport的recv要循环recv到我们需要的长度的数据才行。看了一下thrift erlang 库的最新代码,有几年没有修改了,还是原来年样子,只能自己动手改了,使用第二种方法:新建一个loop_recv函数,最后修改完如下:

测度rpc返回的大数据,小数据,都ok。


作者:wangxiaobo_sz



数据 thrift rpc erlang

需要 登录 后方可回复, 如果你还没有账号请 注册新账号