跳至主要内容
版本:4.0

使用心跳和 TCP Keepalives 检测死 TCP 连接

概述

网络故障的方式多种多样,有时非常微妙(例如,高比例的丢包率)。中断的 TCP 连接需要相当长的时间(例如,在 Linux 上,使用默认配置大约 11 分钟)才能被操作系统检测到。AMQP 0-9-1 提供了一个心跳功能,以确保应用程序层能够立即发现中断的连接(以及完全无响应的对等节点)。心跳还可以防御某些网络设备,这些设备可能会在一段时间内没有活动时终止“闲置”的 TCP 连接。

TCP Keepalives 是一种 TCP 堆栈功能,它起到类似的作用,并且非常有用(可能与心跳结合使用),但需要进行内核调整才能在大多数操作系统和发行版中发挥作用。

心跳超时值

心跳超时值定义了在多长时间后,RabbitMQ 和客户端库会认为对等 TCP 连接不可达(关闭)。此值是在连接时由客户端和 RabbitMQ 服务器协商的。必须将客户端配置为请求心跳。

协商过程的工作方式如下:服务器将建议其可配置的值,客户端将将其与自己的配置值进行协调,并将结果值发送回服务器。该值以为单位,RabbitMQ 建议的默认值为 60

警告

将心跳超时设置为非常低的值会导致误报:连接对等节点被认为不可用,但实际上并非如此

由 RabbitMQ 核心团队维护的 Java、.NET 和 Erlang 客户端使用以下协商算法

  • 如果任一值为 0(见下文),则使用这两个值中较大的值
  • 否则使用这两个值中较小的值

零值表示对等节点建议完全禁用心跳。要禁用心跳,两个对等节点都必须选择加入并使用 0 的值。强烈建议不要这样做,除非已知环境在每个主机上都使用 TCP Keepalives

非常低的值 也不建议使用。

低超时值和误报

信息

5 到 20 秒范围内的值最适合大多数环境

将心跳超时值设置得过低会导致误报(对等节点被认为不可用,但实际上并非如此),原因是瞬态网络拥塞、短暂的服务器流量控制等等。

在选择超时值时,应将此考虑在内。

来自用户和客户端库维护人员多年的反馈表明,低于 5 秒的值相当有可能导致误报,而 1 秒或更低的值则极有可能导致误报。5 到 20 秒范围内的值最适合大多数环境。

心跳帧

心跳帧大约每 心跳超时 / 2 秒发送一次。此值有时被称为 心跳间隔。在错过两个心跳后,对等节点将被视为不可达。不同的客户端表现方式不同,但 TCP 连接将被关闭。当客户端检测到由于心跳而 RabbitMQ 节点不可达时,它需要重新连接。

重要的是不要将超时值与间隔值混淆。RabbitMQ 配置 公开了超时值,官方支持的客户端库也是如此。但是,某些客户端可能会公开间隔,这可能会导致混淆。

任何流量(例如,协议操作、发布的消息、确认)都算作有效心跳。客户端可以选择发送心跳帧,无论连接上是否有其他流量,但有些客户端只在必要时才发送心跳帧。

如何停用心跳

可以通过在连接时将超时间隔设置为 0(在客户端侧),并在服务器心跳也设置为零的情况下,停用心跳。

警告

不建议停用心跳,除非已知环境在每个主机(RabbitMQ 节点和应用程序)上都使用 TCP Keepalives

或者,可以在两端使用非常高的值(例如,1800 秒)来有效地停用心跳,因为帧传递频率太低,不会产生实际影响。

除非使用 TCP Keepalives 代替,并且使用足够低的非活动检测周期,否则强烈建议不要停用心跳。如果停用心跳,则及时检测对等节点不可用变得不太可能,这会对数据安全构成重大风险,尤其是对于 发布者 而言。

使用 Java 客户端启用心跳

要在 Java 客户端中配置心跳超时,请在创建连接之前使用 ConnectionFactory#setRequestedHeartbeat 设置它

ConnectionFactory cf = new ConnectionFactory();

// set the heartbeat timeout to 60 seconds
cf.setRequestedHeartbeat(60);

请注意,如果 RabbitMQ 服务器配置了非零心跳超时(默认值),则客户端只能降低该值,而不能提高该值。

使用 .NET 客户端启用心跳

要在 .NET 客户端中配置心跳超时,请在创建连接之前使用 ConnectionFactory.RequestedHeartbeat 设置它

var cf = new ConnectionFactory();

// set the heartbeat timeout to 60 seconds
cf.RequestedHeartbeat = TimeSpan.FromSeconds(60);

STOMP 中的心跳

STOMP 1.2 包含心跳。在 STOMP 中,心跳超时可以是不对称的:也就是说,客户端和服务器可以使用不同的值。RabbitMQ STOMP 插件完全支持此功能。

STOMP 中的心跳是可选的。要启用它们,请在连接时使用 heart-beat 标头。有关示例,请参见 STOMP 规范

MQTT 中的心跳

MQTT 包含心跳,但名称不同(“保持活动”)。RabbitMQ MQTT 插件完全支持此功能。

MQTT 中的保持活动是可选的。要启用它们,请在连接时设置 keepalive 间隔。有关示例,请咨询您的 MQTT 客户端的文档。

Shovel 和 Federation 插件中的心跳

ShovelFederation 插件在幕后打开到 RabbitMQ 节点的 Erlang 客户端连接。因此,可以将它们配置为使用所需的心跳值。

有关详细信息,请参阅 AMQP 0-9-1 URI 查询参数参考

TCP Keepalives

TCP 包含一种机制,其目的类似于消息协议中的心跳(也称为保持活动)和上面介绍的网络滴答超时:TCP Keepalives。由于默认值不足,不能假定 TCP Keepalives 适合于消息协议。但是,通过适当的调整,它们可以作为一种额外的防御机制,在应用程序无法预期启用心跳或使用合理值的环境中发挥作用。

在某些罕见的情况下,仅使用心跳不足(例如,当所涉及的连接使用不具有某种心跳机制的协议时),必须配置 TCP Keepalives 以使用合理低的超时值。

TCP Keepalives 涵盖主机上的所有 TCP 连接,包括入站和出站连接。这使得它们在以下场景中非常有用:出站连接频繁发生变化,例如,ShovelFederation 插件链接,这些链接经常被停用和重新激活(重新启用)或中断。

通过将 TCP Keepalives 配置为降低系统特定值,也可以使用它们来代替心跳。在这种情况下,可以停用心跳。这种方法的主要好处是,机器上的所有 TCP 连接都将使用相同的值,无论使用什么协议和客户端库。

有关详细信息,请参见 网络指南

心跳和 TCP 代理

某些网络工具(HAproxy、AWS ELB)和设备(硬件负载均衡器)可能会在一段时间内没有活动时终止“闲置”的 TCP 连接。大多数情况下,这不是我们想要的。

当连接上启用心跳时,它会导致周期性的轻量级网络流量。因此,心跳有一个副作用,可以防止代理和负载均衡器过早关闭一段时间内处于空闲状态的客户端连接。

使用 30 秒的心跳超时,连接将大约每 15 秒产生一次周期性的网络流量。5 到 15 秒范围内的活动足以满足大多数流行代理和负载均衡器的默认设置。另请参见上面关于低超时和误报的部分。

排查活动和失效连接

RabbitMQ 节点将记录由于错过心跳而关闭的连接。所有官方支持的客户端库也是如此。检查服务器和客户端日志将提供有价值的信息,应作为首要的故障排除步骤。

可能需要检查打开到节点或来自节点的连接,其状态、来源、用户名和有效的心跳超时值。网络故障排除指南概述了可用于帮助完成此操作的工具。

© 2024 RabbitMQ. All rights reserved.