Thrift RPC Erlang庫大量數據時出錯的解決

我們項目的各個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。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章