我们在connect时常常遇到connection timeout这种错误, 如果你仔细去观察,会发现connect timout分两种情况,

Caused by: java.net.ConnectException: Operation timed out (Connection timed out)

另外一种是:

Caused by: java.net.SocketTimeoutException: connect timed out

那这两种 timeout 有什么区别?分别在什么情况下会发生?

首先无论是哪种语言,不管是客户端还是服务端,在 TCP 编程中通常都可以为 sock 设置一个 timeout 时间。而这个 timeout 又可以细分为 connect timeout、read timeout、write timeout。read timeout 和 write timeout 必须是在 connect 之后才能发生,今天不做过多讨论。上面那两种 timeout 均属于 connect timeout。

另外我们需要补充下 TCP 重传机制的相关知识:

我们知道在 TCP 的三次握手中,Client 发送 SYN,Server 收到之后回 SYN_ACK,接着 Client 再回 ACK,这时 Client 便完成了 connect() 调用,进入 ESTAB 状态。如果 Client 发送 SYN 之后,由于网络原因或者其他问题没有收到 Server 的 SYN_ACK,那么这时 Client 便会重传 SYN。重传的次数由内核参数 net.ipv4.tcp_syn_retries 控制,重传的间隔为 [1,3,7,15,31]s 等

如果 Client 重传完所有 SYN 之后依然没有收到 SYN_ACK,那么这时 connect() 调用便会抛出 connection timeout 错误。如果 Client 在重传 SYN 期间,Client 的 sock timeout 时间到了,那么这时 connect() 会抛出 timeout 错误。

理解net.ipv4.tcp_syn_retries设置

  • net.ipv4.tcp_syn_retries 的设置,表示应用程序进行connect()系统调用时,在对方不返回SYN + ACK的情况下(也就是超时的情况下),第一次发送之后,内核最多重试几次发送SYN包;并且决定了等待时间.
  • Linux上的默认值是 net.ipv4.tcp_syn_retries = 6 ,也就是说如果是本机主动发起连接,(即主动开启TCP三次握手中的第一个SYN包),如果一直收不到对方返回SYN + ACK ,那么应用程序最大的超时时间就是127秒

Linux 系统默认的建立 TCP 连接的超时时间为 127 秒,对于许多客户端来说,这个时间都太长了, 特别是当这个客户端实际上是一个服务的时候,更希望能够尽早失败,以便能够选择其它的可用服务重新尝试。

socket对象是Linux下应用程序需要用到的和远端建立TCP或者UDP连接的对象.

系统调用 connect(2) 则是用来尝试建立 socket 连接(TCP)的函数。 connect 对于 UDP 来说并不是必须的,而对于 TCP 来说则是一个必须过程,著名的 TCP 3 次握手实际上也由 connect 来完成。

网络中的连接超时非常常见,不管是广域网还是局域网,为了一定程度上容忍失败,所以连接加入了重试机制, 而另一方面,为了不给服务端带来过大的压力,重试也是有限制的。

在 Linux 中,连接超时典型为 2 分 7 秒,而对于一些 client 来说,这是一个非常长的时间;

下面来看看 2 分 7 秒是怎样来的,以及怎样配置 Linux kernel 来缩短这个超时。

2 分 7 秒即 127 秒,刚好是 2 的 7 次方减一,聪明的读者可能已经看出来了,如果 TCP 握手的 SYN 包超时重试按照 2 的幂来 backoff, 那么:

第 1 次发送 SYN 报文后等待 1s(2 的 0 次幂),如果超时,则重试
第 2 次发送后等待 2s(2 的 1 次幂),如果超时,则重试
第 3 次发送后等待 4s(2 的 2 次幂),如果超时,则重试
第 4 次发送后等待 8s(2 的 3 次幂),如果超时,则重试
第 5 次发送后等待 16s(2 的 4 次幂),如果超时,则重试
第 6 次发送后等待 32s(2 的 5 次幂),如果超时,则重试
第 7 次发送后等待 64s(2 的 6 次幂),如果超时,则超时失败

上面的结果刚好是 127 秒。也就是说 Linux 内核在尝试建立 TCP 连接时,最多会尝试 7 次。

接下来,我们用实验来进行验证:

首先,配置 iptables 来丢弃指定端口的 SYN 报文

# iptables -A INPUT --protocol tcp --dport 5000 --syn -j DROP

然后,打开 tcpdump 观察到达指定端口的报文

# tcpdump -i lo -Ss0 -n src 127.0.0.1 and dst 127.0.0.1 and port 5000

最后,使用 telnet 连接指定端口

date '+ %F %T'; telnet 127.0.0.1 5000; date '+ %F %T';

从tcpdump的输出也可以看到,一共发了7次SYN包(都是同一个seq号码),第一次是正常请求,后面6次是重试,正是该内核参数 设置的值.

怎样修改 connect timeout

Linux 内核中,net.ipv4.tcp_syn_retries 表示建立 TCP 连接时 SYN 报文重试的次数,默认为 6,可以通过 sysctl 命令查看。

 # sysctl -a | grep tcp_syn_retries
net.ipv4.tcp_syn_retries = 6

将其修改为 1,则可以将 connect 超时时间改为 3 秒,例如:

# sysctl net.ipv4.tcp_syn_retries=1
 date; telnet 127.0.0.1 5000; date;
2020年 06月 19日 星期五 22:16:11 CST
Trying 127.0.0.1...
telnet: connect to address 127.0.0.1: Connection timed out
2020年 06月 19日 星期五 22:16:14 CST

注意:sysctl 修改的内核参数在系统重启后失效,如果需要持久化,可以修改系统配置文件,例如:,对于 CentOS 7 来说,添加 net.ipv4.tcp_syn_retries = 1 到 /etc/sysctl.conf 中即可。

应用层真正的超时时间

那么问题来了,应用层真正的超时时间一定是127秒吗?还是不能大于127秒. 通过上面的实验,基本可以得知应用层的超时间一定不能大于内核的设定. 如果应用层的设定小于内核的设定呢?超时时间应该是小于127秒的.我们继续通过实验来验证下.

现在我的机器上,内核参数是net.ipv4.tcp_syn_retries=6,最大超时时间是 127秒 应用层代码如下:

#!/usr/bin/python
import socket
from datetime import datetime
fmt = "%Y-%m-%d %H:%M:%S"
address = ('127.0.0.1',5000)
s = socket.socket()
s.settimeout(5) #设置socket超时时间为5秒
print datetime.now().strftime(fmt)
s.connect_ex(address)
print datetime.now().strftime(fmt)

我们再来观察下应用程序的表现和tcpdump的输出

python test_socket_connect_timeout.py
2020-06-19 22:10:32
2020-06-19 22:10:37

image.png

从tcpdump的输出看到,第一次发送之后,只尝试了2次重试(2的0次+2的1次),因为第三次重试要等2的2次方秒,也就是4秒, 前面1+2 + 4是7秒,而应用层设置的超时时间是5秒,介于2~3之间,因此第三次重试不会进行. 如果应用程序设置的超时时间足够长,那么第三次重试应该在22:10:39进行.

小结

  • net.ipv4.tcp_syn_retries是用于设置主动发起TCP连接超时时,SYN包的重试次数,该参数如果是x,那么connect(2)调用最大的超时时间为2的x次方 -1,单位是秒.
  • 应用程序最大的超时时间不能超过内核的设定,可以小于等于内核的设定.

ps: 对 TCP 协议栈的理解总是需要慢慢积累

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

彻底理解connection timeout相关推荐

  1. yum 报错:centos yum (28, 'Connection time-out') Trying other mirror.

    问题: 在本地的虚拟机使用yum安装软件时,经常出现 centos yum (28, 'Connection time-out') Trying other mirror. 或下面的那样情况imeou ...

  2. 解决Genymotion下载设备失败的方法(Connection Timeout)

    一直下载不下来,报错. 解决办法: 打开 C:\Users\用户名\AppData\Local\Genymobile目录 打开genymotion.log文件,在里面最下面几行,找到如下日志 [Deb ...

  3. linux上TCP connection timeout的原因查找

    linux上TCP connection timeout的原因查找 好久没有写文章了, 今天解决了一个网络连接超时的问题, 记录以备查看. 最近在线上nginx经常出现输出connection tim ...

  4. Connection Timeout 问题排查

    背景 我们组开发维护了一个 Agent 工程,帮客户采集一些客户有用的网络数据.客户需要下载一个 MSI,然后安装并注册. 问题描述 某个客户下载安装 Agent 之后,提示注册失败.其实 Agent ...

  5. 绝地求生国际服请求超时服务器未响应,绝地求生connection timeout 3.6.7解决方法/游戏连接超时怎么办...

    绝地求生游戏中有很多的玩家遇到了connection timeout 3.6.7,这是怎么回事呢?下面游戏吧小编为大家带来绝地求生connection timeout 3.6.7解决方法,感兴趣的小伙 ...

  6. Connection Timeout和Command Timeout

    每次对数据库连接时,我们有时候会碰到连接超时或者命令超时,这两个超时是不一样的.以ADO.NET为例,当客户端和服务器端连接时,碰到的超时情况主要有下面几种: 当从连接池获取一个连接时,碰到超时. 当 ...

  7. java jedispool实例_Jedis出现connection timeout问题解决方法(JedisPool连接池使用实例)...

    今天发现jedis 默认的连接方式 jedis=new jedis("localhost",6379),老是发生connection timeout. 后来发现jedis类包还有一 ...

  8. IDbConnection的connection timeout 和 IDbcommand.commandTimeout

    郁闷,那天,程序出错,只是简单的判断是某个存储过程执行时间太长,没在意就发给了客户, 谁知道很多都出现time out or server no responding 的错误,还以为是sql conn ...

  9. get connection timeout retry : 1

    错误一:get connection timeout retry : 1 https://github.com/alibaba/druid/issues/4326 生产环境运行一段时间后,报错如下: ...

  10. 关于Flash Player 10 socket connection timeout

    转载请注明,来自:http://blog.csdn.net/skyman_2001 今天我在调试游戏的时候,发现一个有趣的现象,就是flash连接上服务器后,服务器关闭连接,flash会触发secur ...

最新文章

  1. Blender赛车动画制作学习教程 Learn Race Car Animation with Blender
  2. VelocityTracker简单介绍
  3. Mule学习笔记(二)
  4. 2020年度盘点出炉!技术好文一口气读完
  5. 【小题目】输入两个数字以及一个符号,输出这两个数字在这个符号下运算产生的结果
  6. 论文小综 | Pre-training on Graphs
  7. 一加神秘新机入网:搭载天玑8100 首发长寿版150W超级闪充
  8. 【分享】林清玄:有品质的生活,从来都不是钱决定的
  9. Linux下DNS服务器的基本搭建
  10. python编程练习:漏洞百出的四则运算器
  11. IDEA如何设置背景色?
  12. Android优雅地判断软键盘弹出状态
  13. 碧海威 L7多款产品 后台命令执行漏洞
  14. Microsoft Excel 教程:如何在 Excel 中自动填充数据?
  15. Vue中使用Font Awesome
  16. 放弃40 万年薪从字节裸辞,告别 996 拥抱 955…
  17. java.sql.SQLException: Streaming result set com.mysql.jdbc.RowDataDynamic@44f16719 is still active.
  18. Fortran学习3:控制流2:循环
  19. Python中turtle画n层m个不同方向的圆,送你一朵小黄花
  20. 【机器人学】基于PoE模型的串联机械臂UR5的正运动学、微分运动学和逆运动学

热门文章

  1. 音乐格式转换软件测试工资,无损音乐如何转换 无损音乐格式转换 无损音乐转换器...
  2. 寻梦港家政上门服务小程序微擎
  3. 新西兰梅西大学有计算机专业吗,新西兰大学计算机排名第一之梅西大学计算机专业...
  4. PLC可编程控制实验装置及单片机综合实验台
  5. 集成App Linking服务后无法正确跳转到应用的解决方案
  6. 2021-11-15求积分面积和旋转体积的二重积分方法
  7. 2021年下半年市场营销案例分析集锦
  8. 用Nodejs爬取Matrix67的博客
  9. 场外期权:一个你从未了解过的金融衍生品市场正在中国悄悄壮大
  10. 机器人计算机技术,机器人技术与应用