thrift中的超時(timeout)坑

楊俊明發表於2015-12-02

最近在專案中採用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中,是通過設定sendTimeoutrecvTimeout來影響超時的,而且從註釋中的單詞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很強大,也很成熟,但是好用的文件並不多,如果在專案中遇到問題,求人不如求已,除了啃原始碼,還是啃原始碼。 


相關文章