有一台服务器,出现很多的fin_wait1状态的socket。

环境:

[root@localhost ~]# uname -a
Linux localhost.localdomain 2.6.32-358.el6.x86_64

链路情况如下:

ss -s
Total: 2753 (kernel 3336)
TCP: 6046 (estab 730, closed 5001, orphaned 0, synrecv 0, timewait 5000/0), ports 564

Transport Total IP IPv6
* 3336 - -
RAW 1 1 0
UDP 599 599 0
TCP 1045 1037 8
INET 1645 1637 8
FRAG 0 0 0

[root@localhost ~]# ss -t state fin-wait-1

Recv-Q Send-Q Local Address:Port Peer Address:Port
0 384259 server_ip:serverport 10.231.18.150:44581
0 763099 server_ip:serverport 10.231.17.55:45202
0 543095 server_ip:serverport 10.231.22.76:35348
0 2379216 server_ip:serverport 10.231.22.37:56283
0 1237680 server_ip:serverport 10.231.17.161:48815
0 1720677 server_ip:serverport 10.231.16.73:51550
0 619159 server_ip:serverport 10.231.138.28:58986
0 474399 server_ip:serverport 10.231.18.82:45256
0 928420 server_ip:serverport 10.231.20.171:53326
0 27771 server_ip:serverport 10.231.138.38:58963
0 614664 server_ip:serverport 10.231.26.94:51083
0 152535 server_ip:serverport 10.231.19.184:43375

只贴出一部分。

仔细看,发现fin-wait-1的发送队列中,还有一部分数据没有发送到对端,当然用户态close的时候,这种情况是允许的,是没有经过确认的报文缓存。

看fin-wait-1状态的socket占用了多少内存:

ss -tn state fin-wait-1|grep -v Recv-Q|awk 'BEGIN{sum=0}{sum+=$2}END{printf "%.2f\n",sum}'
221797627.00

发现占用还是很多的,因为这个是我在修改tcp_max_orphans为很小的情况下才占用的200多M,事实上在我没处理之前,占用达到了16G。

网上搜索,大多是修改tcp_fin_timeout,其实这个是针对FIN-WAIT-2的。

tcp_fin_timeout- INTEGER Time to hold socket in state FIN-WAIT-2, if it was closed
by our side. Peer can be broken and never close its side,
or even died unexpectedly. Default value is 60sec.
Usual value used in 2.2 was 180 seconds, you may restore
it, but remember that if your machine is even underloaded WEB server, you risk to overflow memory with kilotons of dead sockets,
FIN-WAIT-2 sockets are less dangerous than FIN-WAIT-1,
because they eat maximum 1.5K of memory, but they tend
to live longer. Cf. tcp_max_orphans.

内核中对TCP_FIN_WAIT1的设置是:

} else if (tcp_close_state(sk)) {
/* We FIN if the application ate all the data before
* zapping the connection.
*/

/* RED-PEN. Formally speaking, we have broken TCP state
* machine. State transitions:
*
* TCP_ESTABLISHED -> TCP_FIN_WAIT1
* TCP_SYN_RECV -> TCP_FIN_WAIT1 (forget it, it's impossible)
* TCP_CLOSE_WAIT -> TCP_LAST_ACK
*
* are legal only when FIN has been sent (i.e. in window),
* rather than queued out of window. Purists blame.
*
* F.e. "RFC state" is ESTABLISHED,
* if Linux state is FIN-WAIT-1, but FIN is still not sent.
*
* The visible declinations are that sometimes
* we enter time-wait state, when it is not required really
* (harmless), do not send active resets, when they are
* required by specs (TCP_ESTABLISHED, TCP_CLOSE_WAIT, when
* they look as CLOSING or LAST_ACK for Linux)
* Probably, I missed some more holelets.
* --ANK
*/
tcp_send_fin(sk);

也就是先设置fin-wait-1状态,然后再发fin包,

理论上说,fin-wait-1的状态应该很难看到才对,因为只要收到对方的ack,就应该迁移到fin-wait-2了,如果收到对方的fin,则应该迁移到

closing状态。但是该服务器上就很多。难道没有收到ack或者fin包?抓包验证下:

进而抓包, tcpdump -i eth0  "tcp[tcpflags] & (tcp-fin) != 0" -s 90 -p -n

根据报文,看到了fin包的重传,而有时候刚好遇到对端通告的窗口为0,所以进入fin-wait-1后呆的时间就比较长。

比如我看到fin-wait-1之后,我可以抓之后的交互包,

[root@localhost ~]# ss -to state Fin-wait-1 |head -200 |grep -i 10.96.152.219
0 387543 服务器ip 客户端ip 1 timer:(persist,1.140ms,0)

在这里我们看到了坚持定时器,通过脚本,我获取了fin-wait-1的链路,有的定时器的长度退避之后,达到了120s,然后一直120s进行探测。

在这里说一下脚本的思路:

#!/bin/bash
while [ 1 ]
do
ss -tn state Fin-wait-1 src 服务器ip |awk '{print $4}'|grep -v 服务器端口1|grep -v 服务器端口2|sort -n >caq_old
ss -tn state Fin-wait-1 src 服务器ip |awk '{print $4}'|grep -v 服务器端口1|grep -v 服务器端口1|sort -n >caq_new
diff caq_old caq_new|grep '>'|awk '{print $2}' >diff_caq
sleep 1

###1s之后,重新获取fin-wait-1状态的链路情况,如果新增的链路还存在,那么说明该链路至少存活超过1s,主要是抓坚持定时器比较长的情况
ss -tn state Fin-wait-1 src 服务器ip |awk '{print $4}'|grep -v 服务器端口1|grep -v  服务器端口2|sort -n >caq_new
while read line
do
grep -q $line caq_new
if [ $? -eq 0 ]
then
###live for 1 second
echo $line
exit
else
continue;
fi
done < diff_caq

done

然后抓包:

./get_fin.sh |awk -F '[:]' '{print $2}'|xargs -t tcpdump -i eth1 -s 90 -c 200 -p -n port

可以看到部分抓包:

20:34:26.355115 IP 服务器ip和端口 > 客户端ip和端口: Flags [.], ack 785942062, win 123, length 0
20:34:26.358210 IP 客户端ip和端口 >服务器ip和端口: Flags [.], ack 1, win 0, length 0
20:34:28.159117 IP服务器ip和端口 > 客户端ip和端口: Flags [.], ack 1, win 123, length 0
20:34:28.162169 IP 客户端ip和端口 >服务器ip和端口: Flags [.], ack 1, win 0, length 0
20:34:31.761502 IP 服务器ip和端口 > 客户端ip和端口: Flags [.], ack 1, win 123, length 0
20:34:31.765416 IP 客户端ip和端口 > 服务器ip和端口: Flags [.], ack 1, win 0, length 0

服务器大量的fin_wait1 状态长时间存在原因分析的更多相关文章

  1. 服务器大量的fin_wait1 状态长时间存在原因分析-1

    上文描述了在出现大量fin-wait-1出现的原因,占用的内存等,这里讲一下如何处理这种情况. 首先,fin发送之后,有可能会丢弃,那么发送多少次这样的fin包呢?fin包的重传,也会采用退避方式,在 ...

  2. Nagios状态长时间处于Pending的解决方法

    1 nagios 守护进程引起的一系列问题 1 影响nagios web页面收集监控信息 致使页面出现时而收集不到服务信息 2 影响pnp查看图形化,出图缓慢 3 影响查看服务状态信息,致使有时候查看 ...

  3. 如何查看Windows服务器运行了多长时间

    前言:有时候管理.维护Windows服务器需要定期重启服务器(为什么需要重启,你懂的),但是这个"定期"有时候会受很多因素影响,例如某台服务器忘了重启:某台服务器那个时间段业务繁忙 ...

  4. 想要远程服务器长时间挂机不断开ssh连接的技巧

    使用top命令挂着就好了,top命令执行的“查看系统进程和资源占用”的任务会一直输出动态的数据,一直有数据传输就不会因为长时间挂机而断开ssh链接了,尤其针对于海外服务器,因为高延迟经常出现挂机久了自 ...

  5. SSH连接服务器时,长时间不操作就会断开的解决方案

    最近在配置服务器相关内容时候,不同的事情导致长时间不操作,页面就断开了连接,不能操作,只能关闭窗口,最后通过以下命令解决. SSH连接linux时,长时间不操作就断开的解决方案: 1.修改/etc/s ...

  6. Mongodb 故障分享 初始化时"errmsg" : "exception: new file allocation failure" 并且长时间处于STARTUP2

    Hello,大家下午好. 近几天的项目有点赶,所以耽误了更新.现在给大家分享下,在安装mongodb的过程中,遇到的故障一则.其实很小白的问题,当时遇到这个问题的时候比较心慌,浪费了很多时间,跟大家分 ...

  7. sqlserver中查找长时间未提交事务

    无论是有意无意,如果事务在数据库中保持打开,则它会阻塞其他进程对修改后的数据进行操作.同样,对事务日志进行备份也只会截断不活动事务的那部分事务日志,所以打开的事务会导致日志变多(甚至达到物理限制),直 ...

  8. 实现iOS长时间后台的两种方法:Audiosession和VOIP(转)

    分类: Iphone2013-01-24 14:03 986人阅读 评论(0) 收藏 举报 我们知道iOS开启后台任务后可以获得最多600秒的执行时间,而一些需要在后台下载或者与服务器保持连接的App ...

  9. ASP.NET 工作流:支持长时间运行操作的 Web 应用程序

    ASP.NET 工作流 支持长时间运行操作的 Web 应用程序 Michael Kennedy   代码下载位置:MSDN 代码库 在线浏览代码 本文将介绍以下内容: 独立于进程的工作流 同步和异步活 ...

随机推荐

  1. celery出现警告或异常的解决方式

    做个笔记,记录下使用celery踩过的坑,不定期更新.  warnings.warn(CDeprecationWarning(W_PICKLE_DEPRECATED)) 我用的是Flask,所以在Fl ...

  2. golang 用tar打包文件或文件夹

    打包文件用到了tar包,其中tar包的用法可以参考API golang提供了个函数用来遍历文件夹 filepath.Walk 函数具体描述如下: func Walk(root string, walk ...

  3. linux下的磁盘挂载

    将新的磁盘安装在服务器上后,怎么挂载到现在的服务器上呢? 1.查询是否已经分配磁盘 fdisk -l 这里因为测试,只是挂载了10G的硬盘 2.发现有磁盘/dev/sdb.然后使用fdisk命令建立分 ...

  4. Java框架之Mybatis(二)

    本文主要介绍 Mybatis(一)之后剩下的内容: 1 mybatis 中 log4j的配置 2 dao层的开发(使用mapper代理的方式) 3 mybatis的配置详解 4 输入输出映射对应的类型 ...

  5. Java学习笔记15(面向对象八:匿名对象、内部类)

    匿名对象: 是指创建对象的时候,只有创建对象的语句,却没有把对象地址值赋给某个变量 创建一个普通对象: Person p = new Person(); 创建一个匿名对象: new Person(); ...

  6. java equals == contentEquals

    equals与== 经常用于比较,用法如下:字符串比较相同用equals,普通数值(基本数据类型)比较用==, contentEquals下面讲 理论准备: java的基本类型如int.float,d ...

  7. SGML/HTML/XML之间的关系

    1 历史起源 SGML--1986年国际标准化组织出版发布了一个信息管理方面的国际标准(ISO 8879:1986信息处理). HTML 2.0--1995年11月作为RFC 1866发布 XML 1 ...

  8. django中数据库操作——in操作符

    django一对多关系中,为了实现按照一端查询多端,之前都是用extra操作符,经过查看官方文档还有in这个操作符,用这个实现更简单.直接上代码: 根据查询条件模糊查询所有符合条件的机架列表,然后根据 ...

  9. 【ASP.NET Core】在Win 10 的 Linux 子系统中安装 .NET Core

    在上一篇文章中,老周扯了一下在 Windows 10 中开启 Linux 子系统,并且进行了一些简单的设置.本篇咱们就往上面安装 .net core . 老周假设你从来没有用过 Linux,所以,接着 ...

  10. NYoj289苹果(0-1背包)

    苹果 时间限制:3000 ms  |  内存限制:65535 KB 难度:3 描述 ctest有n个苹果,要将它放入容量为v的背包.给出第i个苹果的大小和价钱,求出能放入背包的苹果的总价钱最大值. 输 ...