Cannot assign requested address 记一次线上问题


“Cannot assign requested address.” 报错是因为客户端频繁连接服务器,每次连接都在很短的时间内结束,导致出现大量的TIME_WAIT,最终导致linux分配的客户端连接端口用尽,无法建立socket连接导致的。
虽然socket可以正常关闭,但是端口并不是马上就释放,而是处于TIME_WAIT状态,默认等待60s后才释放。

服务器解决方法:
sysctl -w net.ipv4.tcp_timestamps=1  开启对于TCP时间戳的支持,若该项设置为0,则下面一项设置不起作用
sysctl -w net.ipv4.tcp_tw_recycle=1  表示开启TCP连接中TIME-WAIT sockets的快速回收tcp_tw_recycle这个参数有点尴尬,4.x内核版本之后这个参数已经被废弃了,可见这个参数有点鸡肋甚至是危险。这个参数表明理解是time_wait回收,就是尽快的回收处于time_wait状态的连接,不用等两个MSL就关闭连接但它的副作用是会拒绝所有比这个客户端时间戳更靠前的网络包。

sysctl -w net.ipv4.tcp_tw_reuse=1  开启tcp_tw_reuse,那么便可以重复利用处于time_wait状态的连接。

那么,大家肯定会好奇,为什么会有TIME_WAIT这个状态呢?这里就需要讲解下TCP/IP协议的设计,特别是四次挥手关闭连接的原理。

我的解决办法:

由于我的业务不光端口占用,而且clickhourse cpu load都飚高,我采用guava 的 RateLimter

对请求限流

网络模型

 

 

 

 

3.TIME_WAIT状态原理(四次挥手、关闭连接)

tcp/ip四次挥手过程示意图

过程说明:
(1)首先,客户端主动要关闭连接,发送FIN包,然后进入FIN_WAIT_1状态,等待服务端返回ACK包。这时客户端不能再向服务端发送数据,但是可以读取数据。
(2)服务端收到FIN包后向客户端发送ACK包,然后进入CLOSE_WAIT状态。此时服务端不能再读取数据,但可以继续向客户端发送数据。
(3)客户端收到服务端发送的ACK包后就进入FIN_WAIT_2状态,等到接收服务端发送的FIN包。
(4)服务端发完成发送数据后,继续发送FIN包给客户端,然后进入LAST_ACK状态,等待客户端返回ACK包。此时,服务端既不能发送数据,也不能读取数据。
(5)客户端收到FIN包后向服务端发送ACK包,然后进入TIME_WAIT状态,等待足够长的时间(2MSL)以确保服务端能接收到ACK包,最后进入CLOSED状态,释放网络资源。
(6)服务端收到客户端发送的ACK包后进入CLOSED状态,释放网络资源。

主动关闭的Socket端会进入TIME_WAIT状态,并且持续2MSL时间长度,MSL就是maximum segment lifetime(最大分节生命期),这是一个IP数据包能在互联网上生存的最长时间,超过这个时间将在网络中消失。MSL在RFC 1122上建议是2分钟,而源自berkeley的TCP实现传统上使用30秒,因而,TIME_WAIT状态一般维持在1-4分钟。
而在这TIME_WAIT状态期间,该socket所占用的本地端口号将一直无法释放,因此在高并发高负载下运行一段时间后,就有可能出现本文所说的错误导致无法创建新的socket连接。

我们看上图的流程,客户端在发送最后一个ACK包以后就跟服务端没有通信,为什么这里还要进入TIME_WAIT状态呢?

4.TIME_WAIT状态存在的理由

(1)可靠地实现TCP全双工连接的终止

确保最后的ACK能让被关闭方接收。 假如主动关闭的一方的发出ACK包,如果这个ACK包丢失,那么服务端将会重新发送FIN包,这时客户端就需要去维护TIME_WAIT状态允许它重发ACK包。如果这时客户端不维持TIME_WAIT状态直接进入CLOSED状态,那么客户端将响应RST分节,服务端收到后会将此分节解释成一个错误(connect reset by peer,即对端已经关闭)。

(2)允许老的重复分节在网络中消逝

TCP是可靠的服务,当数据包丢失会重传,当有数据包迷路的情况下,如果不等待2MSL时,当客户端以同样地方式重新和服务建立连接后,上一次迷路的数据包这时可能会到达服务,这时会造成旧包被重新读取

https://shuwoom.com/?p=1729

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值