Linux下TCP重传的应用控制

对于不耐烦的人:

如何使用setsockopt()ioctl()等更改Linux中单个连接的/proc/sys/net/ipv4/tcp_retries2值,或者是否可能

较长的说明:

我正在开发一个使用长轮询HTTP请求的应用程序。在服务器端,需要知道客户端何时关闭了连接。准确度并不重要,但肯定不能超过15分钟。接近一分钟就可以了

对于那些不熟悉此概念的人,长轮询HTTP请求的工作原理如下:

  • 客户端发送一个请求
  • 服务器使用HTTP头进行响应,但保留打开的响应。使用分块传输编码,允许服务器在数据可用时发送数据位
  • 当发送所有数据时,服务器发送一个;“结束语块”;发出响应完成的信号

在我的应用程序中,服务器发送;心跳“;每一次发送到客户端(默认情况下为30秒)。心跳信号只是作为响应块发送的换行符。这意味着保持线路繁忙,以便我们通知连接丢失

当客户端正确关闭时没有问题。但当强制关闭时(例如,客户端机器断电),不会发送TCP重置。在这种情况下,服务器发送一个心跳信号,客户端不确认。在此之后,服务器在放弃并向应用层(我们的HTTP服务器)报告故障后,继续重新传输数据包大约15分钟。对我来说,15分钟的等待时间太长了

我可以通过写入/proc/sys/net/ipv4/中的以下文件来控制重传时间:

tcp\u重试1-整数
该值会影响TCP决定
由于未确认的RTO重新传输,出现问题,
并向网络层报告这一怀疑。
有关更多详细信息,请参阅tcp_重试2。
RFC 1122建议至少3次重新传输,这是
违约
tcp_重试2-整数
此值影响活动TCP连接的超时,
RTO重传保持未确认状态时。
给定一个值N,假设TCP连接如下
初始RTO为TCP_RTO_MIN的指数退避将
在第(N+1)个RTO终止连接之前,重新传输N次。
默认值15会产生假设的超时924.6
秒,是有效超时的下限。
TCP将在第一个RTO超过
假设超时。
RFC 1122建议超时时间至少为100秒,
对应于至少8的值。

tcp_retries2的默认值实际上是8,我的15分钟(900秒)重传经验与上面引用的内核文档一致

例如,如果我将tcp_retries2的值更改为5,则连接会更快地终止。但是这样设置会影响系统中的所有连接,我真的只想为这个长轮询连接设置它

RFC 1122的报价:

4.2.3.5 TCP连接故障
TCP对同一段的过度重传
表示远程主机或Internet出现故障
路径这种故障可能持续时间短,也可能持续时间长。这个
必须使用以下程序来处理过多的故障
数据段的重新传输[IP:11]:
(a) 有两个阈值R1和R2测量该量
同一时间发生的重传次数
段R1和R2可以用时间单位或
作为重新传输的计数。
(b) 当同一段的传输次数
达到或超过阈值R1,传递负面建议
(见第3.3.1.4节)至IP层,以触发
死网关诊断。
(c) 当同一段的传输次数
达到阈值R2大于R1时,关闭
联系
(d) 应用程序必须能够设置R2的值
一种特殊的联系。例如,一个交互式的
应用程序可能会将R2设置为"“无限”;给用户
控制何时断开连接。
(e) TCP应将交付通知应用程序
问题(除非该信息已被
应用程序;见第4.2.4.1节),当R1为
到达R2之前。这将允许远程登录
(用户Telnet)通知用户的应用程序,
例如

在我看来,Linux中的tcp_重试1tcp_重试2对应于RFC中的R1R2。RFC明确规定(在项目d中),一致性实施必须允许设置R2的值,但我没有找到使用setsockopt()ioctl()或类似方法来实现的方法

另一种选择是在超出R1时获得通知(项目e)。这不如设置R2,不过,我认为R1很快就会被命中(几秒钟之内),并且不能为每个连接设置R1的值,或者至少RFC不需要它

看起来这是在内核2.6.37中添加的。
从内核Git提交diff并从下面的更改日志中摘录

承诺
dca43c75e7e545694a9dd6288553f55c53e2a3a3
作者:朱棣文
日期:2010年8月27日星期五19:13:28+0000

tcp:添加tcp\u用户\u超时套接字选项。
此修补程序提供RFC793中所述的“用户超时”支持。这个
RFC5482“TCP用户的本地部分也需要套接字选项
超时选项”。
TCP_USER_TIMEOUT是一个TCP级别的套接字选项,它接受一个未签名的int,
何时>0,以指定传输的最大时间量(毫秒)
数据可能在TCP强制关闭前保持未确认状态
相应的连接并将ETIMEDOUT返回到应用程序。如果
如果给定0,TCP将继续使用系统默认值。
增加用户超时允许TCP连接在扩展后继续存在
没有端到端连接的时段。减少用户超时
如果需要,允许应用程序“快速失败”。否则可能需要
在正常WAN中,当前系统默认情况下最多20分钟
环境
套接字选项可以在TCP连接的任何状态下进行,但是
仅在连接的同步状态下有效
(已建立、FIN-WAIT-1、FIN-WAIT-2、CLOSE-WAIT、CLOSE或LAST-ACK)。
此外,当与TCP keepalive(SO_keepalive)选项一起使用时,
TCP\u用户\u超时将超过keepalive,以确定何时关闭
由于keepalive失败而导致的连接。
当TCP重新传输数据包时,该选项无论如何都不会更改,也不会更改
将发送keepalive探测器的时间。
与许多其他选项一样,此选项将由接受者从其
听众。
签字人:H.K.Jerry Chu<[email protected]&燃气轮机;
签字人:David S.Miller<[email protected]&燃气轮机;

发表评论