thrift中的超时(timeout)坑

简介: 最近在项目中采用thrift作为后台服务rpc框架,总体用下来性能还不错,跨语言特性使用起来也还行,但是也遇到了一些坑,其中之一就是超时问题(timeout),如果服务端些的某些业务场景耗时较长,thrift client几乎毫无意外的会遇到:Read timed out, 当然解决办法也很容易,thrift client端手动设置一个较长的超时时间即可。

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

目录
相关文章
|
27天前
curl --retry 5 --retry-delay 2 -o curl 超时与重试
curl --retry 5 --retry-delay 2 -o curl 超时与重试
15 0
|
2月前
|
Java Apache
Apache HttpClient 4.5设置超时时间
Apache HttpClient 4.5设置超时时间
|
SQL 网络协议 关系型数据库
mysql 连接超时wait_timeout问题解决
com.mysql.jdbc.CommunicationsException: The last packet successfully received from the server was58129 seconds ago.The last packet sent successfully to the server was 58129 seconds ago, which is longer than the server configured value of 'wait_timeout'. You should consider either expiring and/or tes
|
5月前
|
消息中间件 网络协议 Java
深入剖析阻塞式socket的timeout
深入剖析阻塞式socket的timeout
|
10月前
|
分布式计算 Spark
Spark 3.1.1遇到的 BroadcastQueryStageExec timeout
Spark 3.1.1遇到的 BroadcastQueryStageExec timeout
69 0
|
存储 运维 网络协议
服务端 tcp 连接TIME_WAIT 问题分析与解决
还在等什么,快来一起讨论关注吧,公众号【八点半技术站】,欢迎加入社群
服务端 tcp 连接TIME_WAIT 问题分析与解决
|
数据库
为socket的recv/send设置超时
为socket的recv/send设置超时
225 0
|
SQL 应用服务中间件 Linux
HTTP/2 504 Gateway Timeout 36369ms
HTTP/2 504 Gateway Timeout 36369ms
456 0
HTTP/2 504 Gateway Timeout 36369ms
|
网络协议
TCP Provider The semaphore timeout period has expired
我们一数据库服务器上有个作业最近几天偶尔会遇到下面错误(敏感信息已做处理),主要是报“TCP Provider: The semaphore timeout period has expired. [SQLSTATE 07008] (Error 121)  OLE DB provider "SQLNCLI" for linked server "(null)" returned message "Communication link failure". [SQLSTATE 01000] (Error 7412).  The step failed.”。
2165 0
|
SQL Oracle 关系型数据库
MySQL:参数wait_timeout和interactive_timeout以及空闲超时的实现
水平有限,如果有误请指出源码版本:percona 5.7.22 一、参数意思 这里简单解释一下两个参数含义如下: interactive_timeout:The number of seconds the server waits for activity on an interactive .
2070 0