最近在项目中采用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很强大,也很成熟,但是好用的文档并不多,如果在项目中遇到问题,求人不如求已,除了啃源码,还是啃源码。