使用心跳和 TCP Keepalives 检测死 TCP 连接
概述
网络可能以多种方式失败,有时非常微妙(例如,数据包丢失率很高)。操作系统需要相当长的时间(例如,在 Linux 上使用默认配置大约 11 分钟)才能检测到中断的 TCP 连接。AMQP 0-9-1 提供了一个 心跳 功能,以确保应用程序层能够及时了解中断的连接(以及完全无响应的对等方)。心跳还可以防御某些网络设备,这些设备可能会终止“空闲”的 TCP 连接,因为在一段时间内没有活动。
TCP keepalives 是一个 TCP 堆栈功能,具有类似的目的,并且可能非常有用(可能与心跳结合使用),但需要内核调整才能在大多数操作系统和发行版上实用。
心跳超时值
heartbeat timeout 值定义了 RabbitMQ 和客户端库应认为对等 TCP 连接在多长时间后无法访问(断开)的间隔。此值在连接时由客户端和 RabbitMQ 服务器协商。客户端必须配置为请求心跳。
协商过程如下:服务器将建议其可配置的值,客户端将其与配置的值进行协调,然后将结果值发送回来。该值以秒为单位,RabbitMQ 建议的默认值为 60。
警告将心跳超时设置得非常低可能导致误报:连接的对等方被视为不可用,而实际上并非如此。
RabbitMQ 核心团队维护的 Java、.NET 和 Erlang 客户端使用以下协商算法:
如果任一值为 0(见下文),则使用两个值中较大的一个。
否则,使用两个值中较小的一个。
零值表示对等方建议完全禁用心跳。要禁用心跳,两个对等方都必须选择加入并使用值 0。强烈建议不要这样做,除非环境已知在每个主机上使用 TCP keepalives。
强烈建议不要使用非常低的值。
低超时值和误报
信息对于大多数环境,5 到 20 秒的值是最佳的。
由于瞬态网络拥塞、短暂的服务器流量控制等原因,将心跳超时值设置得太低可能会导致误报(对等方被视为不可用,而实际上并非如此)。
在选择超时值时应考虑这一点。
根据用户和客户端库维护者多年的反馈表明,低于 5 秒的值很有可能导致误报,而 1 秒或更低的值则非常有可能导致误报。对于大多数环境,5 到 20 秒的值是最佳的。
心跳帧
心跳帧大约每 heartbeat timeout / 2 秒发送一次。此值有时称为 heartbeat interval。在两次错过心跳后,对等方将被视为无法访问。不同的客户端表现不同,但 TCP 连接将被关闭。当客户端检测到 RabbitMQ 节点因心跳而无法访问时,它需要重新连接。
请勿将超时值与间隔值混淆。RabbitMQ 的 配置公开超时值,官方支持的客户端库也公开超时值。但是,一些客户端可能会公开间隔值,这可能会导致混淆。
任何流量(例如,协议操作、已发布的消息、确认)都算作有效心跳。客户端可以选择发送心跳帧,而不管连接上是否有其他流量,但有些客户端只在必要时发送。
如何禁用心跳
可以通过在连接时将客户端的心跳超时设置为 0 来禁用心跳,前提是服务器心跳也设置为零。
警告不建议禁用心跳,除非环境已知在每个主机(RabbitMQ 节点和应用程序)上都使用 TCP keepalives。
或者,可以在两端使用非常大的值(例如 1800 秒)来有效地禁用心跳,因为帧传递的频率太低,无法产生实际影响。
除非改用具有足够低的非活动检测周期的 TCP keepalives,否则强烈不建议禁用心跳。如果禁用心跳,将大大降低及时检测对等方不可用的可能性,这将对数据安全构成重大风险,特别是对于发布者。
使用 Java 客户端启用心跳
要在 Java 客户端中配置心跳超时,请在创建连接之前使用 ConnectionFactory#setRequestedHeartbeat 进行设置。
ConnectionFactory cf = new ConnectionFactory();// set the heartbeat timeout to 60 secondscf.setRequestedHeartbeat(60);
请注意,如果 RabbitMQ 服务器配置了非零心跳超时(这是默认设置),则客户端只能降低值,而不能增加值。
使用 .NET 客户端启用心跳
要在 .NET 客户端中配置心跳超时,请在创建连接之前使用 ConnectionFactory.RequestedHeartbeat 进行设置。
var cf = new ConnectionFactory();// set the heartbeat timeout to 60 secondscf.RequestedHeartbeat = TimeSpan.FromSeconds(60);
STOMP 中的心跳
STOMP 1.2 包含心跳。在 STOMP 中,心跳超时可以是不对称的:也就是说,客户端和服务器可以使用不同的值。RabbitMQ STOMP 插件完全支持此功能。
STOMP 中的心跳是可选加入的。要启用它们,请在连接时使用 heart-beat 标头。有关示例,请参阅 STOMP 规范。
MQTT 中的心跳
MQTT 在“keepalives”(保持活动)下包含心跳。RabbitMQ MQTT 插件完全支持此功能。
MQTT 中的保持活动是可选加入的。要启用它们,请在连接时设置 keepalive 间隔。有关示例,请参阅 MQTT 客户端文档。
Shovel 和 Federation 插件中的心跳
Shovel 和 Federation 插件在后台打开到 RabbitMQ 节点的 Erlang 客户端连接。因此,它们可以配置为使用所需的心跳值。
有关详细信息,请参阅 AMQP 0-9-1 URI 查询参数参考。
TCP Keepalives
TCP 包含一个与消息协议中的心跳(又名 keepalive)机制以及上面介绍的 net tick timeout 类似的机制:TCP keepalives。由于默认值不足,TCP keepalives 不能被假定适用于消息协议。但是,通过适当的调整,它们可以作为一种额外的防御机制,适用于无法期望应用程序启用心跳或使用合理值的环境。
在某些罕见情况下,当仅靠心跳不足以解决问题时(例如,当涉及的连接使用没有某种心跳机制的协议时),必须将 TCP keepalives 配置为使用一个相当低的值。
TCP keepalives 涵盖主机上的所有 TCP 连接,包括入站和出站连接。这使得它们在出站连接频繁变动的场景中很有用,例如,Shovel 或 Federation 插件的链接,这些链接经常被禁用、重新激活(重新启用)或中断。
通过将 TCP keepalives 配置为较低的系统特定值,也可以用它们来代替心跳。在这种情况下,心跳可以被禁用。这种方法的主要优点是,机器上的所有 TCP 连接都将使用相同的、与协议和客户端库无关的值。
有关详细信息,请参阅 网络指南。
心跳和 TCP 代理
某些网络工具(HAproxy、AWS ELB)和设备(硬件负载均衡器)可能会在一段时间内没有活动的情况下终止“空闲”的 TCP 连接。大多数情况下,这是不希望的。
当连接上激活心跳时,会产生周期性的轻微网络流量。因此,心跳具有保护空闲一段时间的客户端连接免于被代理和负载均衡器过早关闭的副作用。
当心跳超时设置为 30 秒时,连接大约每 15 秒产生一次周期性网络流量。5 到 15 秒范围内的活动足以满足大多数流行代理和负载均衡器的默认设置。另请参阅上面的低超时和误报部分。
故障排除活动和失效连接
RabbitMQ 节点将记录因错过心跳而关闭的连接。所有官方支持的客户端库也会这样做。检查服务器和客户端日志将提供有价值的信息,并且应该是第一个故障排除步骤。
可能需要检查到节点的连接或从节点发出的连接、它们的状态、来源、用户名和有效心跳超时值。 网络故障排除指南提供了可用工具的概述,以帮助处理此问题。
Copyright © 2022 摩洛哥世界杯_直播世界杯决赛 - dgaida.com All Rights Reserved.