linux端口被占用,netstat查看无进程号,端口状态一直停留在FIN_WAIT1以及CLOSE_WAIT状态

环境信息:

CentOS 6.5

现象:

同事启动程序发现端口被占用,netstat查看之后发现如下现象:

发现端口处于FIN_WAIT1状态以及CLOSE_WAIT状态,无法释放

问题分析:

FIN_WAIT1以及CLOSE_WAIT状态的原理以及产生的原因大家自行baidu,下面就说下怎么解决上述问题,释放端口

FIN_WAIT1:

1、sysctl -a |grep tcp_max_orph(记下 net.ipv4.tcp_max_orphans  的值  第三步需要赋给orig_orphans)  

2、sysctl -w net.ipv4.tcp_max_orphans=0   然后等待FIN_WAIT1的消失,可以用 netstat -np|grep 9080  反复查看,直到没有任何条目

3、sysctl -w net.ipv4.tcp_max_orphans=$orig_orphans

执行完毕查看:

CLOSE_WAIT:

当客户端因为某种原因先于服务端发出了FIN信号,就会导致服务端被动关闭,若服务端不主动关闭socket发FIN给Client,此时服务端Socket会处于CLOSE_WAIT状态(而不是LAST_ACK状态)。通常来说,一个CLOSE_WAIT会维持至少2个小时的时间(系统默认超时时间的是7200秒,也就是2小时)。如果服务端程序因某个原因导致系统造成一堆CLOSE_WAIT消耗资源,那么通常是等不到释放那一刻,系统就已崩溃。因此,解决这个问题的方法还可以通过修改TCP/IP的参数来缩短这个时间,于是修改tcp_keepalive_*系列参数: 
tcp_keepalive_time: 
/proc/sys/net/ipv4/tcp_keepalive_time 
INTEGER,默认值是7200(2小时) 
当keepalive打开的情况下,TCP发送keepalive消息的频率。建议修改值为1800秒。 

tcp_keepalive_probes:INTEGER 
/proc/sys/net/ipv4/tcp_keepalive_probes 
INTEGER,默认值是9 
TCP发送keepalive探测以确定该连接已经断开的次数。(注意:保持连接仅在SO_KEEPALIVE套接字选项被打开是才发送.次数默认不需要修改,当然根据情形也可以适当地缩短此值.设置为5比较合适) 

tcp_keepalive_intvl:INTEGER 
/proc/sys/net/ipv4/tcp_keepalive_intvl 
INTEGER,默认值为75 
当探测没有确认时,重新发送探测的频度。探测消息发送的频率(在认定连接失效之前,发送多少个TCP的keepalive探测包)。乘以tcp_keepalive_probes就得到对于从开始探测以来没有响应的连接杀除的时间。默认值为75秒,也就是没有活动的连接将在大约11分钟以后将被丢弃。(对于普通应用来说,这个值有一些偏大,可以根据需要改小.特别是web类服务器需要改小该值,15是个比较合适的值) 

 

修改方法:

一、 命令修改:(暂时生效,重新启动服务器后,会还原成默认值) 
sysctl -w net.ipv4.tcp_keepalive_time=600   
sysctl -w net.ipv4.tcp_keepalive_probes=2 
sysctl -w net.ipv4.tcp_keepalive_intvl=2 


注意:Linux的内核参数调整的是否合理要注意观察,看业务高峰时候效果如何。 

二、 若做如上修改后,可起作用;则做如下修改以便永久生效。 
vi /etc/sysctl.conf 

若配置文件中不存在如下信息,则添加: 
net.ipv4.tcp_keepalive_time = 1800 
net.ipv4.tcp_keepalive_probes = 3 
net.ipv4.tcp_keepalive_intvl = 15 


编辑完 /etc/sysctl.conf,要重启network 才会生效 
/etc/rc.d/init.d/network restart 
然后,执行sysctl命令使修改生效,基本上就算完成了。

问题总结:

       上述操作完事后,常规的问题应该就能解决了,但是在我的场景中未能解决,CLOSE_WAIT进程未能关闭,因为netstat命令中第二列的REC-Q也就是接收队列不为0,有积压,导致CLOSE_WAIT未能被自动关闭,经排查,发现该端口对应的进程都成为了僵尸进程导致端口无法释放。

      僵尸进程又分为僵尸进程和孤儿进程,区别是通过ps命令查看僵尸进程的PPID是否为空,不为空是僵尸进程,为空是孤儿进程。如果是僵尸进程,处理方式参照我之前的博客https://blog.youkuaiyun.com/microGP/article/details/81509335;如果是孤儿进程,一般情况下操作系统在一定时间内自己就回收了,稍等即可

<think>好的,我现在要帮助用户解决关于容器发起HTTP请求后端口处于CLOSE_WAIT和TIME_WAIT状态的问题。首先,我需要回忆一下这两种状态的含义以及它们在TCP连接生命周期中的位置。 用户提到的是容器环境,可能是在Docker或其他容器平台中运行的应用。当容器发起HTTP请求,也就是作为客户端时,连接结束后端口状态长时间处于CLOSE_WAIT或TIME_WAIT,这会影响系统资源,可能导致端口耗尽或性能下降。 首先,TIME_WAIT状态是正常的,发生在主动关闭连接的一方。根据TCP协议,主动关闭的一方(客户端或服务器)会进入TIME_WAIT,以确保最后的ACK能被对方接收,并处理延迟到达的数据包。通常TIME_WAIT会持续2倍的最大段生存时间(2MSL),在Linux上一般是60秒。如果短时间内有大量连接,TIME_WAIT状态过多会占用端口和内存资源。不过,用户提到的是容器环境,可能需要考虑容器网络的设置,比如端口分配和复用。 然后是CLOSE_WAIT状态,这通常是被动关闭的一方(即服务器端)在接收到FIN包后,但未发送自己的FIN包时进入的状态。如果客户端出现大量CLOSE_WAIT,这可能意味着客户端没有正确关闭连接。例如,客户端在收到服务器的FIN后,没有调用close()方法,导致连接一直停留CLOSE_WAIT。这种情况下,可能是应用程序的代码问题,没有正确释放连接资源。 接下来,我需要考虑容器环境中的特殊性。容器通常使用NAT,出站请求会使用宿主机的端口,但如果是容器内部的问题,比如应用配置或代码问题,可能导致连接未正确关闭。此外,容器的网络命名空间隔离可能会影响端口状态管理。 用户可能需要排查的方向包括: 1. 检查应用代码,确保HTTP客户端正确关闭连接,比如在使用完响应后是否调用了close(),或者是否使用了连接池。 2. 检查容器的网络配置,如是否启用了端口复用(SO_REUSEADDR/SO_REUSEPORT),或者调整TIME_WAIT的超时时间。 3. 系统级参数的调整,比如Linux中的net.ipv4.tcp_tw_reuse和net.ipv4.tcp_tw_recycle,不过需要注意这些参数在较新内核中的变化和潜在问题。 4. 监控和分析连接状态,使用工具如netstat或ss查看具体的连接状态,确定是TIME_WAIT还是CLOSE_WAIT占多数,从而针对性地解决问题。 另外,用户之前询问过Windows中的端口范围设置,可能现在的问题是在Windows容器环境中,或者用户跨平台使用。不过,CLOSE_WAIT和TIME_WAIT是TCP通用状态,处理方式类似,但具体命令和配置可能因系统而异。 需要提醒用户注意,TIME_WAIT是正常现象,除非数量过多导致资源问题,而CLOSE_WAIT通常表示程序有bug,需要修复。在容器环境中,可能需要调整应用或容器运行时的参数来优化连接管理。 最后,总结可能的解决方案,包括应用层面的改进、系统参数的调整以及监控工具的使用,帮助用户逐步排查和解决问题。</think>--- 当容器发起的 HTTP 请求结束后,端口长期处于 `CLOSE_WAIT` 或 `TIME_WAIT` 状态,通常与 **TCP 连接关闭流程异常**或 **资源未释放** 有关。以下是逐步分析与解决方法: --- ### 一、状态含义与根因分析 #### 1. **`TIME_WAIT` 状态** - **触发条件**:主动关闭连接的一方(通常是客户端)会进入 `TIME_WAIT`,持续 **2 倍 MSL(Maximum Segment Lifetime)**(Linux 默认约 60 秒)。 - **作用**:确保网络中残留的旧报文被彻底清除,避免新连接收到干扰。 - **容器中的常见原因**: - 短时间内高频发起 HTTP 请求,导致大量短连接快速关闭。 - 容器未复用 TCP 连接(如未启用 HTTP Keep-Alive)。 - 系统 `TIME_WAIT` 端口回收策略未优化。 #### 2. **`CLOSE_WAIT` 状态** - **触发条件**:被动关闭连接的一方(服务端发送 `FIN` 后,客户端未发送 `FIN` 确认关闭)。 - **本质问题**:**应用程序未正确关闭连接**(如未调用 `close()` 或未释放 Socket 资源)。 - **容器中的常见原因**: - 代码未正确处理连接关闭(如未关闭响应体、未释放 HTTP 客户端)。 - 连接池配置不当,导致资源泄漏。 --- ### 二、问题排查步骤 #### 步骤 1:确认连接状态分布 在容器内执行以下命令,统计当前连接状态: ```bash netstat -tn | awk '/^tcp/ {print $6}' | sort | uniq -c ``` 输出示例: ``` 45 ESTABLISHED 12 TIME_WAIT 8 CLOSE_WAIT ``` #### 步骤 2:定位异常进程 通过 `lsof` 或 `ss` 命令查看占用 `CLOSE_WAIT` 的进程: ```bash lsof -iTCP -sTCP:CLOSE_WAIT ``` --- ### 三、解决方案 #### 针对 `TIME_WAIT` 过多 1. **启用 HTTP 连接复用**: - 在 HTTP 客户端(如 Python `requests`、Java `HttpClient`)中启用 Keep-Alive。 - 示例(Python): ```python session = requests.Session() response = session.get("http://example.com") # 复用同一 TCP 连接 ``` 2. **调整系统参数**(需容器权限): - 修改 Linux 内核参数(在容器宿主机或容器内): ```bash # 允许复用 TIME_WAIT 端口 sysctl -w net.ipv4.tcp_tw_reuse=1 # 加快 TIME_WAIT 回收(谨慎使用,可能影响 NAT 环境) sysctl -w net.ipv4.tcp_tw_recycle=0 # 建议保持关闭,避免 NAT 问题 ``` #### 针对 `CLOSE_WAIT` 过多 1. **修复应用程序代码**: - **强制释放资源**:确保所有 HTTP 响应体(如 `Response.Body`)被关闭。 - 示例(Go): ```go resp, err := http.Get("http://example.com") defer resp.Body.Close() // 必须显式关闭 ``` 2. **检查连接池配置**: - 设置合理的连接池大小和超时时间,避免连接泄漏。 - 示例(Java HttpClient): ```java PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(); cm.setMaxTotal(100); // 最大连接数 cm.setDefaultMaxPerRoute(10); // 每路由最大连接数 ``` --- ### 四、容器环境特殊优化 1. **调整临时端口范围**(缓解 `TIME_WAIT` 端口耗尽): ```bash # 在宿主机或容器内(需权限) sysctl -w net.ipv4.ip_local_port_range="1024 65000" ``` 2. **启用 `tcp_fin_timeout` 优化**: ```bash sysctl -w net.ipv4.tcp_fin_timeout=30 # 缩短 FIN 超时(默认 60 秒) ``` --- ### 五、关键总结表 | 状态 | 根本原因 | 解决方案 | 优先级 | |------------|---------------------------|-----------------------------------|---------| | `TIME_WAIT`| 短连接高频创建 | 复用连接 + 调整内核参数 | 高 | | `CLOSE_WAIT`| 应用未关闭连接 | 修复代码 + 检查连接池 | 紧急 | --- ### 六、验证方法 1. **监控连接状态变化**: ```bash watch -n 1 "netstat -tn | awk '/^tcp/ {print \$6}' | sort | uniq -c" ``` 2. **使用压力测试工具验证**: ```bash ab -n 1000 -c 100 http://example.com/ ``` 通过上述步骤,可显著减少异常状态连接,避免端口资源耗尽或性能下降。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值