最近在項目中采用thrift作為后臺服務rpc框架,總體用下來性能還不錯,跨語言特性使用起來也還行,但是也遇到了一些坑,其中之一就是超時問題(timeout),如果服務端些的某些業務場景耗時較長,thrift client幾乎毫無意外的會遇到:Read timed out, 當然解決辦法也很容易,thrift client端手動設置一個較長的超時時間即可。
下面才是真正吐槽的開始:
既然號稱跨語言,至少各個語言在實現底層功能時,API應該保持一致吧,比如java中的有一個XXXTimeout的屬性,php中應該也有這個屬性吧,然而并不是這樣的,不僅超時設置的方法名(屬性名)不同,連TMD的時間單位都不一致。
而且這種問題,幾乎在網上也查不到資料,只能查看源碼,在thrift源碼(目前最新的是0.9.3)的lib包下,有名種語言的實現,可以找幾個來瞅瞅:
php版:
文件位置:thrift-0.9.3/lib/php/lib/Thrift/Transport/TSocket.php
1 /** 2 * Send timeout in seconds. 3 * 4 * Combined with sendTimeoutUsec this is used for send timeouts. 5 * 6 * @var int 7 */ 8 private $sendTimeoutSec_ = 0; 9 10 /** 11 * Send timeout in microseconds. 12 * 13 * Combined with sendTimeoutSec this is used for send timeouts. 14 * 15 * @var int 16 */ 17 private $sendTimeoutUsec_ = 100000; 18 19 /** 20 * Recv timeout in seconds 21 * 22 * Combined with recvTimeoutUsec this is used for recv timeouts. 23 * 24 * @var int 25 */ 26 private $recvTimeoutSec_ = 0; 27 28 /** 29 * Recv timeout in microseconds 30 * 31 * Combined with recvTimeoutSec this is used for recv timeouts. 32 * 33 * @var int 34 */ 35 private $recvTimeoutUsec_ = 750000;
在php中,是通過設置sendTimeout及recvTimeout來影響超時的,而且從注釋中的單詞microseconds可以看出,時間單位為『微秒』,但同樣在這個文件中,繼續向下看,
1 /** 2 * Sets the send timeout. 3 * 4 * @param int $timeout Timeout in milliseconds. 5 */ 6 public function setSendTimeout($timeout) 7 { 8 $this->sendTimeoutSec_ = floor($timeout / 1000); 9 $this->sendTimeoutUsec_ = 10 ($timeout - ($this->sendTimeoutSec_ * 1000)) * 1000; 11 } 12 13 /** 14 * Sets the receive timeout. 15 * 16 * @param int $timeout Timeout in milliseconds. 17 */ 18 public function setRecvTimeout($timeout) 19 { 20 $this->recvTimeoutSec_ = floor($timeout / 1000); 21 $this->recvTimeoutUsec_ = 22 ($timeout - ($this->recvTimeoutSec_ * 1000)) * 1000; 23 }
到了真正設置的地方,按注釋上的描述,又換成了milliseconds(毫秒),不明白為啥要這么折騰,php不太懂,根據http://blog.csdn.net/zf2371752658/article/details/40148399 這篇文章中的1樓回復來看,正確的理解應該是微秒。
c#版:
文件位置:thrift-0.9.3/lib/csharp/src/Transport/TSocket.cs
1 public int Timeout 2 { 3 set 4 { 5 client.ReceiveTimeout = client.SendTimeout = timeout = value; 6 } 7 }
干脆就全統一成Timeout這一個屬性了,而且沒給任何注釋說明什么時間單位。
java版:
文件位置:thrift-0.9.3/lib/java/src/org/apache/thrift/transport/TSocket.java
1 /** 2 * Sets the socket timeout and connection timeout. 3 * 4 * @param timeout Milliseconds timeout 5 */ 6 public void setTimeout(int timeout) { 7 this.setConnectTimeout(timeout); 8 this.setSocketTimeout(timeout); 9 } 10 11 /** 12 * Sets the time after which the connection attempt will time out 13 * 14 * @param timeout Milliseconds timeout 15 */ 16 public void setConnectTimeout(int timeout) { 17 connectTimeout_ = timeout; 18 } 19 20 /** 21 * Sets the socket timeout 22 * 23 * @param timeout Milliseconds timeout 24 */ 25 public void setSocketTimeout(int timeout) { 26 socketTimeout_ = timeout; 27 try { 28 socket_.setSoTimeout(timeout); 29 } catch (SocketException sx) { 30 LOGGER.warn("Could not set socket timeout.", sx); 31 } 32 }
又拆成了3個成員:Timeout,ConnectTimeout,SocketTimeout了,時間單位從注釋上看,是毫秒。
js版:(你沒有看錯,thrift client還支持node js/javascript)
文件位置:thrift-0.9.3/lib/js/src/thrift.js
通篇全文查找,也沒到關于"timeout"的內容
個人猜測:造成這種亂象的原因是不同語言的客戶端實現,是由不同團隊完成的,每個團隊各自為陣,沒有一個上層的牽頭人來強制約束API規范。
結論:thrift很強大,也很成熟,但是好用的文檔并不多,如果在項目中遇到問題,求人不如求已,除了啃源碼,還是啃源碼。
文章列表