大量close_wait以及调用ip地址错误获取方法引发的故障

本文记录了针对网关服务器在高并发访问下出现的大量Close_wait现象及访问速度减缓问题进行的分析与解决过程。通过调整服务器关闭策略和优化IP获取方式,有效提升了服务器性能。
记录一下这几天帮助兄弟项目组解决的几个问题

工程:网关服务器,业务逻辑少,操作不费时
问题:大量的Close_wait,访问速度较慢

分析&解决:
1、close_wait是TCP/IP协议中被动关闭方收到Fin后没有发送Fin导致
项目采用了mina框架,服务器被动关闭时会生成一个异常,调用exceptionCaught()方法,
在该方法中,服务器调用关闭方法session.close(false);false的意思是先发送数据,等数据 发送完了再关闭。通常情况下这是一个正常的流程,但是在高并发访问的情况下,可能生成大量Close_wait。如果情况允许的话,把false改成true就好了。通常情况下,改成true是没有问题的。

2、项目中获取ip的方法有问题:
  ip = ((InetSocketAddress)(session.getRemoteAddress())).getHostName();

此方法会先通过域名服务器获取远程客户段的域名,域名无法获得的情况下再获取ip,在域名服务器不稳定的情况下,通常耗时好几百毫秒。如果没有必要的话,可以将这个代码直接修改为:
	InetSocketAddress accountAddress = (InetSocketAddress) session
.getRemoteAddress();

String accountIp = accountAddress.getAddress().getHostAddress();
服务启动后出现大量 `CLOSE_WAIT` 连接通常表明服务端在关闭连接时存在问题,具体表现为服务端在接收到客户端的 `FIN` 报文后,未能及时发送 `FIN` 报文以完成四次挥手的关闭流程。这种状态表明连接已经从客户端关闭,但服务端尚未完成关闭操作,导致连接处于半关闭状态并持续占用资源。 ### 1. 确认 CLOSE_WAIT 的来源 首先,可以通过 `netstat` 或 `ss` 命令查看当前系统中处于 `CLOSE_WAIT` 状态的连接数量及其来源: ```bash netstat -antp | grep CLOSE_WAIT ``` 或者 ```bash ss -antp | grep CLOSE_WAIT ``` 通过这些命令可以获取到具体的连接信息,包括本地和远程的 IP 地址及端口号,以及对应的进程 ID(PID)。随后可以结合 `lsof -i :<端口>` 或 `ps -p <PID>` 来定位具体的应用程序。 ### 2. 检查应用程序代码逻辑 `CLOSE_WAIT` 状态的出现通常与应用程序的代码逻辑有关。特别是在网络通信中,服务端在读取完客户端发送的数据后,未能正确关闭连接。常见的问题包括: - **未正确关闭输入流或输出流**:在 Java 应用中,如果只关闭了 `OutputStream` 而没有关闭 `InputStream`,或者反之,可能导致连接未被完全关闭。 - **阻塞在读操作**:如果服务端在等待客户端发送数据时发生阻塞,且未设置合理的超时机制,可能导致连接无法及时关闭。 - **资源泄漏**:未正确释放连接资源,例如未调用 `close()` 方法,或未在 `finally` 块中关闭连接。 因此,应检查代码中涉及网络通信的部分,确保所有连接在使用完毕后都能被正确关闭。例如,在 Java 中应确保类似以下代码结构: ```java try (Socket socket = new Socket()) { // 使用 socket 进行通信 } catch (IOException e) { e.printStackTrace(); } ``` ### 3. 检查系统资源限制 系统级别的资源限制也可能导致 `CLOSE_WAIT` 连接堆积。例如,文件描述符的最大数量限制可以通过以下命令查看: ```bash ulimit -n ``` 如果当前系统中打开的文件描述符接近上限,可能会导致新的连接无法正常关闭。可以通过修改 `/etc/security/limits.conf` 文件来调整用户的文件描述符限制: ``` * soft nofile 65536 * hard nofile 65536 ``` ### 4. 分析日志和监控信息 查看应用程序的日志,尤其是与网络连接相关的部分,确认是否存在异常或错误信息。例如,是否在关闭连接时抛出异常,或者是否有未处理的异常导致连接未被关闭。 此外,可以使用监控工具(如 `top`、`htop`、`iostat` 等)检查系统的 CPU、内存和 I/O 使用情况,确认是否存在资源瓶颈或阻塞操作。 ### 5. 调整内核参数(谨慎操作) 在某些情况下,可能需要调整内核参数来优化连接关闭的行为。例如,可以通过修改 `/proc/sys/net/ipv4/tcp_keepalive_time` 和 `/proc/sys/net/ipv4/tcp_fin_timeout` 来调整 TCP 保活时间和 FIN 超时时间: ```bash echo 300 > /proc/sys/net/ipv4/tcp_keepalive_time echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout ``` 这些参数的调整应基于实际的网络环境和应用需求,建议在测试环境中验证后再应用于生产环境。 ### 6. 使用工具进行深度分析 - **`tcpdump`**:可以使用 `tcpdump` 抓取网络流量,分析连接的关闭过程是否完整。 - **`strace`**:通过 `strace` 跟踪进程的系统调用,查看是否在 `close()` 调用上出现问题。 - **`jstack`(针对 Java 应用)**:如果问题是由于 Java 应用引起的,可以使用 `jstack` 查看线程堆栈信息,确认是否有线程阻塞在 I/O 操作上。 ### 7. 验证修复效果 在完成上述排查和修复操作后,重新启动服务并观察 `CLOSE_WAIT` 连接的数量变化。如果问题得到缓解,说明修复措施有效。如果问题依然存在,可能需要进一步分析网络环境、第三方库或中间件的行为。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值