关于操作系统TCP keepalive功能使用的说明

 

作者:李烨楠

文章来自微信公众号平台人生


环境:(产品,平台,机型,软件版本,等)
RS6000 AIX 6.1、7.1

问题描述:
man手册中关于no的参数“tcp_keepidle”的含义:
指定保持一个空闲TCP连接活动的时间长度,以半秒测量。
客户发现他的应用在系统上生成的半连接在到达tcp_keepidle规定的时间后并没有被系统中断回收。
我们用telnet进行了测试实验:
<环境>
两个节点使用AIX7.1操作系统
<实验一>
1.在节点 node1 改变tcp_keepidle的值:

  1. #no -p -o tcp_keepidle=60 -------------->30秒

2.在节点 node2使用tcpdump命令trace IP 包:

  1. #tcpdump -i en1 -l dst host node2 and src host node1

3.从 node2 telnet 到 node1 -------------------->node1 做服务器
在这个测试中,我们可以看到当达到tcp_keepidle规定的30秒后,node1发送了一个keepalive的测试包给node2来测试空闲连接。

<实验二>
1.在节点 node1 改变tcp_keepidle的值:

  1. #no -p -o tcp_keepidle=60 -------------->30秒

2.在节点 node2使用tcpdump命令trace IP 包:

  1. #tcpdump -i en1 -l dst host node2 and src host node1

3.从 node1 telnet 到 node2 -------------------->node1 做客户端
在这个测试中,我们可以看到当达到tcp_keepidle规定的30秒后,node1并没有发送keepalive的测试包。

我们将同样的测试在AIX7.1平台上也做了一次,结果是相同的。
根据测试结果,我们发现tcp_keepidle只在做服务器时生效,如果节点作为telnet的客户端,这个参数就没有起到应有的作用。

解答:

如何及时有效地检测到一方的非正常断开,一直有两种技术可以运用。一种是由TCP协议层实现的Keepalive,另一种是由应用层自己实现的心跳包。
由于Keepalive功能一直存在争议,因此,并没有直接写入TCP/IP的协议中,但是各个操作系统基本都实现了这个功能,因此默认并不开启Keepalive功能。
因此,如果要使用系统的keepalive功能,应用必须在建立socket连接时声明KEEPALIVE flag,否则此功能不生效。

可以用如下方法查看某一个socket连接是否声明了KEEPALIVE flag:

1). find the connection:

  1. #netstat -Aan|grep 23
  2. PCB/ADDR Proto Recv-Q Send-Q Local Address Foreign Address
  3. (state)
  4. f100060009978b98 tcp4 0 0 84.32.81.1.23 84.7.112.223.3392
  5. ESTABLISHED

2). Write down the PCB/ADDR for each established connection (value in the first column).

3). check the socket information in kdb

  1. #echo "sockinfotcpcb" | kdb>sockinfo.out
  2. ...
  3. ---- SOCKET INFO ----(@ F100060004724008)----
  4. type........ 0001 (STREAM)
  5. opts........ FFFF810C (REUSEADDR|KEEPALIVE|OOBINLINE|AUDIT)
  6. keepalive flag
  7. linger...... 0000 state....... 0102 (ISCONNECTED|NBIO)

关于应用声明使用操作系统KEEPALIVE功能的参数说明:

SO_KEEPALIVE

Monitors the activity of a connection by enabling or disabling the
periodic transmission of ACK messages on a connected socket. The idle
interval time can be designated using the TCP/IP no command. Broken
connections are discussed in "Understanding Socket Types and Protocols"
in AIX 5L Version 5.3 Communications Programming Concepts.

If an application has keepalive enabled by setting the
setsockopt function call SO_KEEPALIVE, then AIX will use tcp_keepidle
network option to send a probe to the client to check if there is still
a network connection. The server will send 8 probes to the client after
2 hrs.of idle time or inactivity (by default) to check if the
connection still exists. If the client doesn't respond to the 8 probes
with an acknowledgement, then the server closes the socket connection.

If the application doesn't have SO_KEEPALIVE enabled and if the client goes away then AIX's tcp_keepidle option is ignored and the socket stays open until the next reboot of the system or if the application is shutdown.

结论:
经过进一步的检查,我发现telnet的服务器端软件创建socket时声明了KEEPALIVE flag,而telnet客户端软件没有声明KEEPALIVE flag.

因此才会出现之前的实验结果。

另外,我还测试了ftp服务,服务器和客户端两端均使用了SO_KEEPALIVE功能,因此两端操作系统都会检查空闲TCP连接并予以回收。

最后的结论就是,如果要使用操作系统的TCP keepalive回收功能,必须要求对应的服务器或客户端应用程序使用SO_KEEPALIVE参数加以声明才行。

posted @ 2020-04-03 12:01  小小毛竹  阅读(1001)  评论(0)    收藏  举报