`
san_yun
  • 浏览: 2651638 次
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

TCP连接状态异常记录

    博客分类:
  • TCP
 
阅读更多

参考:http://blueskykong.com/2018/07/26/tcp-close-wait/

问题描述

分布式事务Lottor在测试环境中运行一段时间之后,出现Lottor客户端连接不上Lottor Server的情况。经过排查,发现根源问题是Lottor客户端获取不到Lottor Server的集群信息。

Lottor Server启动了两个端口:9666为Tomcat容器的端口、9888为netty 服务器的端口。通过如下命令查看端口的状态:

1
netstat -apn

netty服务的端口

1
netstat -apn|grep 9888

首先查看了netty服务器的端口,连接很正常,和我们上面描述的问题没什么联系。排除netty服务连接的因素。

Tomcat容器的端口

其次查看Tomcat容器的端口的状态:

1
netstat -apn|grep 9666

发现有大量的FIN_WAIT2 和 CLOSE_WAIT状态的连接。
image

另外还可以通过如下的命令查看当前的连接数:

1
netstat -apn|grep 9666 | wc -l

更加细化可以发现FIN_WAIT2 和 CLOSE_WAIT状态的连接数量相当。

TCP四次挥手

通信的客户端和服务端通过三次握手建立TCP连接。当数据传输完毕后,双方都可释放连接。最开始的时候,客户端和服务器都是处于ESTABLISHED状态,然后客户端主动关闭,服务器被动关闭。

image

连接的主动断开是可以发生在客户端,也同样可以发生在服务端。常用的三个状态是:ESTABLISHED 表示正在通信,TIME_WAIT 表示主动关闭,CLOSE_WAIT 表示被动关闭。

ESTABLISHED

最开始的时候,客户端和服务器都是处于ESTABLISHED状态,然后客户端或服务端发起主动关闭,另一端则是被动关闭。

FIN_WAIT1

当一方接受到来自应用断开连接的信号时候,就发送 FIN 数据报来进行主动断开,并且该连接进入 FIN_WAIT1 状态,连接处于半段开状态(可以接受、应答数据,当不能发送数据),并将连接的控制权托管给 Kernel,程序就不再进行处理。一般情况下,连接处理 FIN_WAIT1 的状态只是持续很短的一段时间。

CLOSE_WAIT

被动关闭的一端在收到FIN包文之后,其所处的状态为CLOSE_WAIT,表示被动关闭。

FIN_WAIT2

当主动断开一端的 FIN 请求发送出去后,并且成功够接受到相应的 ACK 请求后,就进入了 FIN_WAIT2 状态。其实 FIN_WAIT1 和 FIN_WAIT2 状态都是在等待对方的 FIN 数据报。当 TCP 一直保持这个状态的时候,对方就有可能永远都不断开连接,导致该连接一直保持着。

TIME_WAIT

从以上TCP连接关闭的状态转换图可以看出,主动关闭的一方在发送完对对方FIN报文的确认(ACK)报文后,会进入TIME_WAIT状态。TIME_WAIT状态也称为2MSL状态。MSL值得是数据包在网络中的最大生存时间。产生这种结果使得这个TCP连接在2MSL连接等待期间,定义这个连接的四元组(客户端IP地址和端口,服务端IP地址和端口号)不能被使用。

原因分析

在上一小节介绍了TCP四次挥手的相关状态之后,我们将会分析在什么情况下,连接处于CLOSE_WAIT状态呢?
在被动关闭连接情况下,已经接收到FIN,但是还没有发送自己的FIN的时刻,连接处于CLOSE_WAIT状态。
通常来讲,CLOSE_WAIT状态的持续时间应该很短,正如SYN_RCVD状态。但是在一些特殊情况下,就会出现连接长时间处于CLOSE_WAIT状态的情况。

出现大量close_wait的现象,主要原因是某种情况下对方关闭了socket链接,但是另一端由于正在读写,没有关闭连接。代码需要判断socket,一旦读到0,断开连接,read返回负,检查一下errno,如果不是AGAIN,就断开连接。

Linux分配给一个用户的文件句柄是有限的,而TIME_WAIT和CLOSE_WAIT两种状态如果一直被保持,那么意味着对应数目的通道就一直被占着,一旦达到句柄数上限,新的请求就无法被处理了,接着就是大量Too Many Open Files异常,导致tomcat崩溃。关于TIME_WAIT过多的解决方案参见TIME_WAIT数量太多

常见错误原因

从原理上来讲,由于Server的Socket在客户端已经关闭时而没有调用关闭,造成服务器端的连接处在“挂起”状态,而客户端则处在等待应答的状态上。此问题的典型特征是:一端处于FIN_WAIT2 ,而另一端处于CLOSE_WAIT。具体来说:

1.代码层面上未对连接进行关闭,比如关闭代码未写在 finally 块关闭,如果程序中发生异常就会跳过关闭代码,自然未发出指令关闭,连接一直由程序托管,内核也无权处理,自然不会发出 FIN 请求,导致连接一直在 CLOSE_WAIT 。

2.程序响应过慢,比如双方进行通讯,当客户端请求服务端迟迟得不到响应,就断开连接,重新发起请求,导致服务端一直忙于业务处理,没空去关闭连接。这种情况也会导致这个问题。

Lottor中的问题

Lottor中,客户端定时刷新本地存储的Lottor Server的地址信息,具体来说是每60秒刷新一次,通过HttpClient请求获取结果。笔者根据网上查找的资料和如上的分析,首先尝试将周期性刷新关闭,观察Lottor Server的9666端口的连接数。之前线性增长的连接数停了下来,初步定位到问题的根源。

服务器A是一台爬虫服务器,它使用简单的HttpClient去请求资源服务器B上面的apache获取文件资源,正常情况下,如果请求成功,那么在抓取完 资源后,服务器A会主动发出关闭连接的请求,这个时候就是主动关闭连接,服务器A的连接状态我们可以看到是TIME_WAIT。如果一旦发生异常呢?假设 请求的资源服务器B上并不存在,那么这个时候就会由服务器B发出关闭连接的请求,服务器A就是被动的关闭了连接,如果服务器A被动关闭连接之后程序员忘了 让HttpClient释放连接,那就会造成CLOSE_WAIT的状态了。

笔者的场景如上面的情况一般,该问题的解决方法是我们在遇到异常的时候应该直接调用中止本次连接,以防CLOSE_WAIT状态的持续。案例可以参见HttpClient连接池抛出大量ConnectionPoolTimeoutException: Timeout waiting for connection异常排查。笔者后来的改进方法是重写了这部分的逻辑,由Spring Cloud FeignClient调用执行,避免之前的负载均衡查询等繁琐的操作。

参考

  1. HttpClient连接池抛出大量ConnectionPoolTimeoutException: Timeout waiting for connection异常排查
  2. 网络连接无法释放—— CLOSE_WAIT
  3. TCP三次握手四次挥手详解
分享到:
评论

相关推荐

    查看系统的TCP连接情况

    开发者可以通过查看TCP连接状态来定位程序在通信过程中的问题,如连接失败、数据传输错误等。 总的来说,实时查看系统的TCP连接情况是维护网络安全、优化系统性能和解决问题的关键步骤。通过使用像Tcpview这样的...

    TCP连接监控源代码

    1. **连接监听器**:持续扫描打开和关闭的TCP连接,记录连接的元数据,如源IP、目标IP、端口号和连接状态。 2. **数据包捕获**:可能使用libpcap库或WinPCAP库来捕获网络接口上的原始数据包,解析TCP头部信息。 3. *...

    tcp连接查看工具

    4. **日志记录**:某些工具可能支持日志功能,可以记录TCP连接的变化,这对于跟踪网络活动和排查问题非常有用。 5. **命令行选项**:tcpvcon.exe可能提供命令行参数,允许用户通过脚本自动化某些操作,例如定期捕获...

    TCP连接监控程序

    TCP连接监控程序是用于跟踪和分析TCP连接状态的工具,帮助开发者诊断网络问题,优化应用程序性能。在这个场景中,我们讨论的是一个使用API接口实现的TCP连接监控程序,它具有类封装的设计,提高了代码的可读性和易用...

    TCP连接监控.rar

    通过分析和实践易语言TCP连接监控源码,我们可以了解如何在程序中实现对TCP连接的监控,包括监听网络接口、解析TCP报文、记录连接状态变化等。此外,这也有助于开发者掌握网络编程的基本原理,提高解决实际问题的...

    易语言源码易语言TCP连接监控源码.rar

    8. **状态监控**:源码中可能会包含对连接状态的监控,例如记录连接的建立、断开时间,统计连接次数,以及异常情况的报警等。 9. **日志记录**:为了方便调试和问题追踪,通常会将通信过程中的关键信息记录到日志...

    TCP连接信息查看器.rar

    1. **故障排查**:当网络出现问题时,查看器可以帮助定位是哪个连接出了问题,如是否因为端口被占用或连接状态异常导致的。 2. **性能监控**:可以监控TCP连接的数量、活跃状态以及带宽使用情况,评估网络性能。 3. ...

    TCP连接信息查看器1.rar

    4. **日志记录**:记录TCP连接的历史信息,便于分析网络问题。 5. **性能分析**:统计网络带宽使用情况,分析网络性能瓶颈。 使用TCP连接信息查看器1,用户可以有效地诊断网络问题,例如排查连接延迟、丢包或异常...

    modbus TCP连接 java工具包

    Modbus TCP连接与Java工具包是工业自动化领域中常见的通信技术与编程语言的结合。Modbus是一种广泛应用的工业通信协议,允许设备之间进行简单、有效的数据交换,而TCP(Transmission Control Protocol)是网络协议栈...

    API监控TCP连接.rar

    - **日志记录**:记录所有重要的API调用和TCP连接状态变化,方便后期分析。 - **报警机制**:当监控指标达到预设阈值时,触发报警通知开发团队。 - **统计分析**:对API调用频率、成功率和TCP连接性能进行统计,提供...

    使用SNMP建立对TCP连接的监控.rar_SNMP_tcp

    在本主题中,“使用SNMP建立对TCP连接的监控”意味着我们将探讨如何通过SNMP来监视网络中的TCP连接状态,以确保网络服务的稳定性和性能。 首先,理解SNMP的基本概念至关重要。SNMP由三部分组成:管理信息库(MIB)...

    取TCP连接列表.rar

    4. **数据结构**:TCP连接信息通常以表格形式返回,包含多个记录,每个记录可能包含以下字段: - 连接状态(如ESTABLISHED, SYN_SENT, FIN_WAIT1等)。 - 本地IP地址和端口。 - 远程IP地址和端口。 - 连接的相关...

    TCP连接查看

    TCP连接查看是一个重要的网络诊断工具,它主要用于监测和分析本机的TCP连接状态。在日常的IT工作中,理解和掌握TCP连接对于排查网络问题、优化应用性能以及确保网络安全至关重要。TCP(Transmission Control ...

    用于调试tcp连接用于调试tcp连接

    - **netstat**:命令行工具,可以显示TCP连接的状态,如ESTABLISHED(已建立)、LISTEN(监听)等。 - **tcpdump**:类似于Wireshark,用于抓取网络包,适用于命令行环境。 - **telnet**:简单网络调试工具,可以...

    易语言源码TCP连接信息查看器.rar

    4. **数据结构与解析**:在处理TCP连接信息时,程序会遇到各种数据结构,如IP地址结构、TCP连接状态结构等。源码中会展示如何解析这些结构,将原始数据转化为可读性强的用户界面信息。 5. **用户界面设计**:易语言...

    基于TCP的全连接端口扫描

    全连接端口扫描,也称为TCP Connect扫描,是指扫描者向目标主机的每一个端口发送SYN报文,然后完成三次握手,建立一个完整的TCP连接。如果目标主机的端口处于监听状态,它会响应SYN+ACK报文,并且扫描者会发送ACK...

    易语言TCP连接监控源码.zip易语言项目例子源码下载

    7. **日志记录与数据显示**:在TCP连接监控中,记录连接状态和数据交互过程对于调试和分析非常重要。可以设置日志系统,将关键信息输出到文件或控制台,同时在用户界面上实时显示连接信息。 8. **用户界面设计**:...

    监控TCP连接.zip易语言项目例子源码下载

    当有新的TCP连接尝试时,程序会捕获这一事件,并进行相应的处理,如记录连接信息、显示连接状态等。 在实际应用中,这样的监控系统可以用于多种场景。例如,它可以作为服务器健康检查工具,实时反馈服务器的连接...

    tcpview 本地网络连接请求查看

    TCPView能够实时显示本机所有TCP和UDP连接的详细信息,包括进程ID、远程IP地址、远程端口、本地端口以及连接状态等。 首先,我们要理解TCP(传输控制协议)和UDP(用户数据报协议)是网络通信中的两种主要协议。TCP...

    TCPTrace-TCP追踪

    3. **报文分析**:它能解析TCP报文头,揭示TCP选项和标志,如SYN、ACK、FIN、RST等,帮助分析连接状态和异常情况。 4. **时间线显示**:TCPTrace提供了时间线视图,清晰展示每个事件发生的时间顺序,便于理解网络...

Global site tag (gtag.js) - Google Analytics