Cannot assign requested address问题解决

本文探讨了在大量高并发日志传输过程中遇到的TIME_WAIT状态过多问题,深入解析其产生的原因,并提供了一系列可行的解决方案,包括修改系统配置、调整应用逻辑等。

TIME_WAIT过多及解决

问题场景

大量高并发日志传输,短连接,每次在传输一定数量的日志后,开始出现以下错误

    Failed to establish a new connection: [Errno 99] Cannot assign requested address

问题原因

通过下述命令可以查看当前端口占用及分类

    netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"\t",state[key]}'

    TIME_WAIT        27352
    SYN_SENT         4
    ESTABLISHED      58

 发现端口占用中处于TIME_WAIT状态的有多达20000+,基本占用了全部的端口,要详细了解端口状态,需要从TCP的状态转换说起。

image

  其中TIME_WAIT状态的产生源自于TCP连接的结束,TCP要保证在所有可能的情况下使得所有的数据都能够正确被投递。当关闭一个 socket 连接时,主动关闭一端的 socket 将进入TIME_WAIT状态,而被动关闭一方则转入CLOSED状态。

当一个socket关闭的时候,是通过两端互发信息的四次握手过程完成的,当一端调用close()时,就说明本端没有数据再要发送了。这好似看来在握手完成以后,socket就都应该处于关闭CLOSED状态了。但这有两个问题: 
1. 我们没有任何机制保证最后的一个ACK能够正常送达 
2. 网络上仍然有可能有残余的数据包(wandering duplicates,或老的重复数据包),我们也必须能够正常处理。

  正常的系统中,可分配的端口号是有限的,但是处于TIME_WAIT状态的连接,虽然已经要确认关闭了,但是仍然占住端口不撒手,一般需要2MSL的时间,现实时长大概在两分钟左右,所以在有限的端口使用完之后,新的请求没有可以安放的地方,便出现了上述错误。

解决方案

  1. 修改sysctl.conf

    vim /etc/sysctl.conf
    
    # 文件中加入
    
    net.ipv4.tcp_tw_reuse = 1 
    net.ipv4.tcp_tw_recycle = 1 
  2. 减少短时间内的请求数 
    这一条需要结合具体场景分析,像本例的场景,是一个短时间内高并发,短连接,每次传输的时间较短,所以可以考虑加大每次的请求的数据传输量,总量一定的情况下,请求数下来,端口使用也能得到一定程度的缓解。

  3. 通过直接发送RTS来直接结束本次连接 
    这个方法暂时没实践,如果有时间,后期可能补上

Refs

TCP/IP详解–TCP连接中TIME_WAIT状态过多 
发现大量的TIME_WAIT解决办法

你遇到的现象是: - 连续 **四次**执行 `ubus call network.interface.wan down/up` 命令,并出现了四次: ``` ioctl: Cannot assign requested address ``` - **最终一次成功获取了新的 IP**。 - 但之前尝试时,**即使接口 down/up 成功,IP 也没有变化**。 --- ## ✅ 问题分析 ### 🔍 为什么会出现 `ioctl: Cannot assign requested address`? 这个错误通常发生在以下几种情况: #### 1. **接口尚未完全释放资源** - 执行 `down` 后,底层资源(如 IP、路由、socket)可能未完全释放。 - 马上执行 `up` 时,系统尝试绑定旧的 IP 地址失败,从而报错。 #### 2. **DHCP 客户端未重启或未清除 lease 文件** - 即使你执行了接口 down/up,**DHCP 客户端可能仍然持有旧的 lease 信息**。 - 所以即使接口 up 成功,它依然尝试申请之前的 IP。 #### 3. **DHCP 客户端未被触发重新获取** - `ubus call network.interface.wan up` 并不会强制触发 DHCP 请求。 - 有些情况下需要**手动重启 DHCP 客户端或使用 `ifup`** 才能触发。 --- ## ✅ 为什么最后一次成功获取新 IP? 最后一次成功获取新 IP 的可能原因: #### ✔️ 1. **lease 文件被自动清除** - 在多次 down/up 后,系统可能清除了旧的 lease 文件,导致 DHCP 客户端重新发起 Discover 请求。 #### ✔️ 2. **DHCP 客户端被重新触发** - 某次 `up` 操作后,DHCP 客户端重新启动,成功获取了新的 IP。 #### ✔️ 3. **网络状态最终被刷新** - 经过多次 down/up,系统资源最终被完全释放并重建,从而允许新 IP 被分配。 --- ## ✅ 推荐做法(避免重复尝试失败) ### ✅ 正确流程(推荐) ```bash # 1. 关闭 wan 接口 ubus call network.interface.wan down # 2. 删除 lease 文件(关键步骤!) rm -f /tmp/dhcp-wan.lease # 3. 重启 DHCP 客户端(可选) killall udhcpc && sleep 1 udhcpc -i $(uci get network.wan.ifname) -n -q & # 或者直接使用 ifup(更推荐) ifdown wan ifup wan ``` --- ## ✅ 小技巧 - 查看 DHCP 客户端是否运行: ```bash ps | grep udhcpc ``` - 查看接口当前状态: ```bash ubus call network.interface.wan status ``` - 查看当前 IP: ```bash ifconfig wan ``` --- ## ✅ 总结 | 操作 | 是否推荐 | 说明 | |------|----------|------| | `ubus call down/up` | ⚠️ 部分有效 | 不一定触发完整 DHCP 获取 | | 清除 lease 文件 | ✅ 必须操作 | 强制 DHCP 客户端重新获取新 IP | | 使用 `ifdown/ifup` | ✅ 强烈推荐 | 更彻底的接口重启方式 | | 手动重启 DHCP 客户端 | ✅ 高级用法 | 控制更精细,适用于调试 | | 查看接口状态 | ✅ 必须操作 | 确认 IP 是否更新 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值