TCP的状态转换及生产问题实操

栏目: 服务器 · 发布时间: 5年前

内容简介:前文介绍了TCP协议主要的流程,包括建立连接、传输数据和断开连接。如果大家认真阅读了附图,应该可以看到在各个流程中套接字的状态是在不断变化的,不同的状态标识了套集字所处的阶段。如图1是TCP一个完整的状态转换图,图中包含了套接字的所有状态,以及发生状态转变的触发条件。可能会有人问,了解这些状态有什么用呢?我们平时编程又用不到。

前文介绍了TCP协议主要的流程,包括建立连接、传输数据和断开连接。如果大家认真阅读了附图,应该可以看到在各个流程中套接字的状态是在不断变化的,不同的状态标识了套集字所处的阶段。

如图1是TCP一个完整的状态转换图,图中包含了套接字的所有状态,以及发生状态转变的触发条件。可能会有人问,了解这些状态有什么用呢?我们平时编程又用不到。

TCP的状态转换及生产问题实操

图1 TCP状态转换图

为了说明上述问题,我们从3个角度进行解释,分别是各种状态的含义、在系统层面如何查询状态和在实际生产中的应用。

一、各种状态的含义

在回答问题之前我们先具体了解一下各个状态的含义。

  • CLOSED:这个是套接字的初始状态,表示TCP连接是新建“未打开的”状态或者已经“关闭着的”。
  • LISTEN :这个是服务端仅有的状态,表示服务器端的某个SOCKET处于监听状态,可以接受客户端的连接。
  • SYN_RCVD :表示服务器接收到了来自客户端请求连接的SYN报文。在正常情况下,这个状态我们可能观察不到,因为这个状态是服务器端的SOCKET在建立TCP连接时的三次握手会话过程中的一个中间状态,很短暂。
  • SYN_SENT :这个状态与SYN_RCVD 状态相呼应,当客户端SOCKET执行connect()进行连接时,它首先发送SYN报文,然后随即进入到SYN_SENT 状态,并等待服务端的发送三次握手中的第2个报文。SYN_SENT 状态表示客户端已发送SYN报文。
  • ESTABLISHED :表示TCP连接已经成功建立。
  • FIN_WAIT_1 :这个状态得好好解释一下,其实FIN_WAIT_1 和FIN_WAIT_2 两种状态的真正含义都是表示等待对方的FIN报文。而这两种状态的区别是:FIN_WAIT_1状态实际上是当SOCKET在ESTABLISHED状态时,它想主动关闭连接,向对方发送了FIN报文,此时该SOCKET进入到FIN_WAIT_1 状态。而当对方回应ACK报文后,则进入到FIN_WAIT_2 状态。当然在实际的正常情况下,无论对方处于任何种情况下,都应该马上回应ACK报文,所以FIN_WAIT_1 状态一般是比较难见到的,而FIN_WAIT_2 状态有时仍可以用netstat看到。
  • FIN_WAIT_2 :上面已经解释了这种状态的由来,实际上FIN_WAIT_2状态下的SOCKET表示半连接,即有一方调用close()主动要求关闭连接。注意:FIN_WAIT_2 是没有超时的(不像TIME_WAIT 状态),这种状态下如果对方不关闭(不配合完成4次挥手过程),那这个 FIN_WAIT_2 状态将一直保持到系统重启,越来越多的FIN_WAIT_2 状态会导致内核crash。
  • TIME_WAIT :表示收到了对方的FIN报文,并发送出了ACK报文。 TIME_WAIT状态下的TCP连接会等待2*MSL(Max Segment Lifetime,最大分段生存期,指一个TCP报文在Internet上的最长生存时间。)在 Linux 可以通过cat /proc/sys/net/ipv4/tcp_fin_timeout看到本机的这个值,然后即可回到CLOSED 可用状态了。
  • CLOSING :这种状态在实际情况中应该很少见,属于一种比较罕见的例外状态。正常情况下,当一方发送FIN报文后,按理来说是应该先收到(或同时收到)对方的ACK报文,再收到对方的FIN报文。但是CLOSING 状态表示一方发送FIN报文后,并没有收到对方的ACK报文,反而却也收到了对方的FIN报文。什么情况下会出现此种情况呢?那就是当双方几乎在同时close()一个SOCKET的话,就出现了双方同时发送FIN报文的情况,这是就会出现CLOSING 状态,表示双方都正在关闭SOCKET连接。
  • CLOSE_WAIT :表示正在等待关闭。怎么理解呢?当对方close()一个SOCKET后发送FIN报文给自己,你的系统毫无疑问地将会回应一个ACK报文给对方,此时TCP连接则进入到CLOSE_WAIT状态。接下来呢,你需要检查自己是否还有数据要发送给对方,如果没有的话,那你也就可以close()这个SOCKET并发送FIN报文给对方,即关闭自己到对方这个方向的连接。有数据的话则看程序的策略,继续发送或丢弃。简单地说,当你处于CLOSE_WAIT 状态下,需要完成的事情是等待你去关闭连接。
  • LAST_ACK :当被动关闭的一方在发送FIN报文后,等待对方的ACK报文的时候,就处于LAST_ACK 状态。当收到对方的ACK报文后,也就可以进入到CLOSED 可用状态了。

二、状态的监控方法

前文已经有提及,可以通过netstat命令查看TCP连接的状态。图2是一个简单的例子,执行该命令的时候不带任何参数。

TCP的状态转换及生产问题实操

图2 netstat执行结果

由上图可以看出,通过netstat可以看到每个TCP连接和UDP的状态和详细的IP地址等信息。该命令有很多参数,通过不同的参数可以得到我们想要的内容。下面我们举几个具体的例子。

1. 显示所有端口信息

可以通过-a参数列出所有端口信息,而且可以附带-t只列出TCP协议的,或者-u只列出UDP协议的端口信息。

[root@itworld123~]# netstat -a # 列出所有端口 
[root@itworld123~]# netstat -at # 列出所有TCP端口 
[root@itworld123~]# netstat -au # 列出所有UDP端口 

2. 显示所有监听状态的套接字

可以通过-l参数列出所有处于监听状态的套接字。当然也可以结合-t或者-u参数获取想要的信息。如下是获取TCP处于监听状态的套接字列表:

root@itworld123:~# netstat -lu 

TCP的状态转换及生产问题实操

图3 监听状态列表

3. 查看服务状态

可以查看具体的服务的监听和套接字等状态。例如下面命令用于查看ssh服务的状态:

root@itworld123:~#netstat -antp | grep ssh 

TCP的状态转换及生产问题实操

图3 SSH状态结果

4. 其它

当然,也可以通过 shell 脚本实现复杂的查询,比如下面用于统计ESTABLISHED状态的数量。

netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}' 

netstat命令功能非常强大,由于篇幅问题,本文只能抛砖引玉,更多功能可以man一下看看,这里就不过多解释。

三、实际生产环境的意义

前面啰嗦了一大堆,我们回到正题,了解这些状态到底有什么用呢?我们知道Linux操作系统对文件句柄的总量是有限制的,套接字也属于文件句柄,因此也是有限制的。了解套接字的状态有助于我们了解服务器是否有隐患或者性能瓶颈。

说到这,可能有的同学还是不明白,我们举个简单的例子。假设一台服务器最多有6万个句柄,如果由于某种业务场景,在服务器端出现大量的TIME_WAIT,此时这些套接字是无法马上释放,也就是无法马上被重复使用,但仍然占用6万句柄的名额。这块,随着时间的推移,可能会耗尽所有句柄,从而导致有新的连接请求是服务器端无法响应的问题。

为了让大家更形象的理解这些状态在实际生产中的意义,我们举几个实际生产中遇到问题的例子。

1. 服务器端大量TIME_WAIT

(1) 现象描述

某对象存储服务,在监控系统发现有大量的TIME_WAIT。经确认该服务器是一台新上架接入的服务器。经反复确认,具备相同功能的同集群的其它服务器工作都正常,并不存在大量TIME_WAIT的情况。

(2) 问题分析

结合协议我们知道主动关闭方会处于该状态,而且TIME_WAIT状态下的TCP连接会等待2*MSL。因此我们查看系统配置cat /proc/sys/net/ipv4/tcp_fin_timeout,发现是默认值。因此,确定是等待时间太长,导致套接字无法被利用所致。

(3) 问题解决

通过调整内核参数解决,打开文件/etc/sysctl.conf,编辑文件,加入以下内容:

net.ipv4.tcp_syncookies = 1 
net.ipv4.tcp_tw_reuse = 1 
net.ipv4.tcp_tw_recycle = 1 
net.ipv4.tcp_fin_timeout = 30 

然后执行/sbin/sysctl -p让参数生效。

上述内容的含义具体如下:

  • net.ipv4.tcp_syncookies = 1表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
  • net.ipv4.tcp_tw_reuse = 1表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
  • net.ipv4.tcp_tw_recycle = 1表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
  • net.ipv4.tcp_fin_timeout修改系統默认的TIMEOUT时间

2. 服务器端大量ESTABLISHED

(1) 问题描述

某Tomcat服务器出现大量ESTABLISHED连接。

(2) 问题分析

根据协议状态转换情况,初步推断是tomcat服务器回收session时出了问题,这个一般都跟服务器的Timeout设置有联系。

查看tomcat的配置文件 server.xml

<Connector port="8080" protocol="HTTP/1.1" 
 connectionTimeout="20000" 
 redirectPort="8443" URIEncoding="UTF-8" /> 
***** 

我们重点关注一下connectionTimeout,这个配置导致建立一个socket连接后,如果一直没有收到客户端的FIN,也没有数据过来,那么此连接也必须等到10s后,才能被超时释放。由于服务器并发量大,而该超时时间有长,导致连接释放严重滞后,因此出现大量的ESTABLISHED连接。

(3) 问题解决

分析上述问题后,我们有针对性的作出如下修改。

connectionTimeout="20000" 改为 connectionTimeout="100" 
acceptCount="100"改为acceptCount="5000" 

修改后问题解决。

实际的例子还很多,但万变不离其宗,需要我们熟悉TCP协议和状态转换,这样在实际生产中遇到问题就可以有理有据的进行分析,然后轻松解决。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

An Introduction to Probability Theory and Its Applications

An Introduction to Probability Theory and Its Applications

William Feller / Wiley / 1991-1-1 / USD 120.00

Major changes in this edition include the substitution of probabilistic arguments for combinatorial artifices, and the addition of new sections on branching processes, Markov chains, and the De Moivre......一起来看看 《An Introduction to Probability Theory and Its Applications》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

随机密码生成器
随机密码生成器

多种字符组合密码