Linux - 关闭连接太多

时间:2016-08-08 20:11:59

标签: linux sockets netty

我正在使用Netty(异步nio)以1800连接/分钟的速度在单个linux机器上编写应用程序。如果没有收到应答,则连接会持续几秒钟然后关闭或在20秒后超时。此外,读/写超时为30秒,请求头包含connection=close。 一段时间(2-3小时)后,我在日志中遇到很多异常,因为由于缺乏资源,Netty无法创建新的连接。 我将limits.conf中打开文件的最大数量增加为:

root            hard    nofile           200000
root            soft    nofile           200000

以下是netstat -nat | awk '{print $6}' | sort | uniq -c | sort -n的输出:

   1 established)
   1 FIN_WAIT2
   1 Foreign
   2 TIME_WAIT
   6 LISTEN
  739 SYN_SENT
 6439 LAST_ACK
 6705 CLOSE_WAIT
12484 ESTABLISHED

这是ss -s命令的输出:

Total: 194738 (kernel 194975)
TCP:   201128 (estab 13052, closed 174321, orphaned 6477, synrecv 0, timewait 3/0), ports 0

Transport Total     IP        IPv6
*         194975    -         -
RAW       0         0         0
UDP       17        12        5
TCP       26807     8         26799
INET      26824     20        26804
FRAG      0         0         0

同样ls -l /proc/2448/fd | wc -l给出约199K。

也就是说,问题是关于ss -s命令输出中报告的已关闭连接:

1)他们究竟是什么?

2)为什么他们不停地晃来晃去?

3)是否有任何设置(超时或其他)可以帮助将它们保持在合理的限度内?

3 个答案:

答案 0 :(得分:1)

  

1)他们究竟是什么?

它们是从未连接或断开连接且不是close d。

的套接字

在Linux中,传出的TCP套接字经历以下各个阶段(大致):

  1. create套接字(未连接),内核为其分配文件描述符。
  2. connect()它到远程端,建立网络连接。
  3. 您进行数据传输(读/写)。
  4. 完成阅读/写作后,您shutdown()读取和写入套接字,关闭网络连接。
  5. close()套接字,内核释放文件描述符。
  6. 所以那些174K连接ss报告已关闭的是套接字,这些套接字要么没有超过第1阶段(可能connect()失败,甚至从未调用过),要么已经过第4阶段,但不是5阶段。有效地,它们是具有底层打开文件描述符的套接字,但没有任何网络绑定(因此netstat / ss列表不显示它们。)

      

    2)为什么他们不停地晃来晃去?

    因为没有人打电话给close()。我会称之为“文件描述符泄漏”或“套接字描述符泄漏”。

      

    3)是否有任何设置(超时或其他)可以帮助将它们保持在合理的限度内?

    从Linux的角度来看,没有。您必须在它们上显式调用close()(或终止拥有它们的进程,以便内核知道它们不再被使用)。

    从Netty / Java的角度来看,也许,我不知道。

    本质上,它是代码中的错误,或Netty代码(不太可能)或JRE代码中的错误(更不可能)。您应该在应该的时候释放资源。如果您显示代码,也许有人可以发现错误。

答案 1 :(得分:1)

正如Roman正确指出的那样,闭合连接确实存在,并且是从未正确关闭的套接字。 就我而言,我有一些线索可以解决我在下面报告的问题:

1)ss -s显示了奇怪的值,特别是很多已关闭的连接

2)ls -l /proc/pid/fd | wc -l显示了很多开放描述符

3)netstat -nat | awk '{print $6}' | sort | uniq -c | sort -n中的数字与之前的数字不匹配

4)sudo lsof -n -p pid(罗马建议)显示了很多条目无法识别协议

在网上浏览我发现了一篇有趣的帖子(https://idea.popcount.org/2012-12-09-lsof-cant-identify-protocol/),它解释了第4点可能意味着什么以及为什么netstat数字不匹配(另见https://serverfault.com/questions/153983/sockets-found-by-lsof-but-not-by-netstat)。

我很惊讶,因为我使用了netty 4.1.x(使用Spring),其中每个连接应该被正确关闭,所以我花了几天时间才弄清楚错误是什么。

微妙的问题出现在netty IO线程中,邮件正文被复制并放入阻塞队列(作为我的代码的一部分)。当队列已满时,这会减慢速度,引入一些延迟并导致我的终端未检测到连接超时,从而导致FD泄漏。

我的解决方案是引入一种池化队列,以防止队列满时的网络请求。

答案 2 :(得分:0)

您仍然没有提供我要求的确切错误消息,但据我所知,问题应该是关于处于CLOSE_WAIT状态的六千五百个连接,而不是那些已关闭的连接' #39;

您没有关闭对等方断开连接的套接字。

  

那就是说,问题是那些封闭的联系。

什么是封闭连接?您的netstat显示屏未显示任何已关闭的关联。并且没有证据表明您的资源耗尽问题与封闭连接有关。

  

1)他们究竟是什么?

他们不是。

  

2)为什么他们不停地晃来晃去?

他们没有。

  

3)是否有任何设置(超时或其他)可以帮助将它们保持在合理的限度内?

由于它们不存在,这个问题毫无意义。