网络连接故障排除
概述
本指南与一篇关于网络的指南相辅相成,重点介绍网络连接的故障排除。
对于使用 TLS 的连接,还有一个额外的TLS 故障排除指南。
故障排除方法
网络连接问题的故障排除是一个广泛的话题。关于它已经写了整本书。本指南解释了一种方法和广泛可用的网络工具,可以帮助有效地缩小最常见的问题。
网络协议是分层的。与之相关的故障也是如此。有效的故障排除策略通常使用排除法来查明问题(或多个问题),从较高级别开始。特别是对于消息传递技术,以下步骤通常有效且足够
- 验证客户端配置
- 使用
rabbitmq-diagnostics listeners
、rabbitmq-diagnostics status
、rabbitmq-diagnostics environment
验证服务器配置 - 检查服务器日志
- 验证主机名解析
- 验证使用了哪些 TCP 端口及其可访问性
- 验证IP 路由
- 如果需要,获取并分析流量转储(流量捕获)
- 验证客户端是否可以成功进行身份验证
这些步骤按顺序执行时,通常有助于识别大多数网络问题的根本原因。低于互联网(网络)层级别的故障排除工具和技术不在本指南的范围内。
某些问题仅在连接频繁变化的环境中才会发生。可以使用管理 UI检查客户端连接。还可以检查节点的所有 TCP 连接及其状态。随着时间的推移收集的信息,结合服务器日志,将有助于检测连接变化、文件描述符耗尽和相关问题。
验证客户端配置
所有开发人员和运营人员都遇到过这种情况:错别字、过时的值、预配工具中的问题、混淆的公钥和私钥路径等。第一步是仔细检查应用程序和客户端库配置。
验证服务器配置
验证服务器配置有助于证明 RabbitMQ 正在使用与网络相关的预期设置集运行。它还验证节点是否确实正在运行。以下是推荐的步骤
- 使用
rabbitmq-diagnostics status
确保节点正在运行 - 验证配置文件是否放置正确,并具有正确的语法/结构
- 使用
rabbitmq-diagnostics listeners
或rabbitmq-diagnostics status
中的listeners
部分检查监听器 - 使用
rabbitmq-diagnostics environment
检查有效配置
请注意,在较旧的 RabbitMQ 版本中,status
和environment
命令仅作为rabbitmqctl的一部分提供:rabbitmqctl status
等。在现代版本中,可以使用任一工具运行这些命令,但rabbitmq-diagnostics是大多数文档指南通常推荐使用的。
listeners 部分将如下所示
Interface: [::], port: 25672, protocol: clustering, purpose: inter-node and CLI tool communication
Interface: [::], port: 5672, protocol: amqp, purpose: AMQP 0-9-1 and AMQP 1.0
Interface: [::], port: 5671, protocol: amqp/ssl, purpose: AMQP 0-9-1 and AMQP 1.0 over TLS
Interface: [::], port: 15672, protocol: http, purpose: HTTP API
Interface: [::], port: 15671, protocol: https, purpose: HTTP API over TLS (HTTPS)
Interface: [::], port: 1883, protocol: mqtt, purpose: MQTT
在上面的示例中,节点上有 6 个 TCP 监听器
- 端口
25672
上的节点间和CLI 工具通信 - 端口
5672
上用于非 TLS 连接的 AMQP 0-9-1(如果启用,则为 1.0)监听器 - 端口
5671
上用于启用 TLS 的连接的 AMQP 0-9-1(如果启用,则为 1.0)监听器 - 端口 15672(HTTP)和 15671(HTTPS)上的HTTP API监听器
- 端口 1883 上用于非 TLS 连接的MQTT监听器
在第二个示例中,节点上有 4 个 TCP 监听器
- 端口
25672
上的节点间和CLI 工具通信 - 端口
5672
上用于非 TLS 连接的 AMQP 0-9-1(如果启用,则为 1.0)监听器 - 端口
5671
上用于启用 TLS 的连接的 AMQP 0-9-1(如果启用,则为 1.0)监听器 - 端口 15672(仅限 HTTP)上的HTTP API监听器
所有监听器都绑定到所有可用的接口。
检查节点使用的 TCP 监听器有助于发现非标准端口配置、应该配置但未配置的协议插件(例如MQTT)、节点仅限于少数网络接口的情况等。如果端口不在监听器列表中,则表示节点无法接受该端口上的任何连接。
检查服务器日志
RabbitMQ 节点将记录关键客户端连接生命周期事件。必须成功建立 TCP 连接,并且对端必须至少发送 1 个字节的数据,连接才被视为(并记录为)已接受。
从这一点开始,连接握手和协商将按照所用消息传递协议(例如 AMQP 0-9-1、AMQP 1.0 或 MQTT)的规范进行。
如果未记录任何事件,则表示要么没有成功的入站 TCP 连接,要么它们未发送任何数据。
主机名解析
应用程序在连接到 RabbitMQ 时使用包含主机名的主机名或 URI 非常常见。dig和nslookup是用于故障排除主机名解析的常用工具。
端口访问
除了主机名解析和 IP 路由问题外,外部连接的 TCP 端口不可访问也是导致客户端连接失败的常见原因。telnet是一个常用的、非常简单的工具,用于测试到特定主机和端口的 TCP 连接。
以下示例使用telnet
连接到端口5672
上的主机localhost
。有一个使用默认设置在localhost
上运行的正在运行的节点,并且没有任何内容阻止对端口的访问,因此连接成功。然后输入12345
作为输入,然后按 Enter。这些数据将通过打开的连接发送到节点。
由于12345
不是正确的 AMQP 0-9-1 或 AMQP 1.0 协议头,因此服务器关闭 TCP 连接
telnet localhost 5672
# => Trying ::1...
# => Connected to localhost.
# => Escape character is '^]'.
12345 # enter this and hit Enter to send
# => AMQP Connection closed by foreign host.
telnet
连接成功后,使用Control + ]
,然后使用Control + D
退出。
以下示例连接到端口5673
上的localhost
。连接失败(被操作系统拒绝),因为没有进程在该端口上侦听。
telnet localhost 5673
# => Trying ::1...
# => telnet: connect to address ::1: Connection refused
# => Trying 127.0.0.1...
# => telnet: connect to address 127.0.0.1: Connection refused
# => telnet: Unable to connect to remote host
失败或超时telnet
连接强烈表明存在代理、负载均衡器或防火墙阻止对目标端口的传入连接。也可能是由于 RabbitMQ 进程未在目标节点上运行或使用非标准端口。这些情况应在仔细检查服务器监听器配置的步骤中排除。
有大量的防火墙、代理和负载均衡器工具和产品。iptables是 Linux 和其他类 Unix 系统上常用的防火墙。网络上不乏iptables
教程。
可以使用netstat、ss、lsof检查节点的开放端口、TCP 和 UDP 连接。
以下示例使用lsof
显示在端口 5672 上侦听并使用 IPv4 的操作系统进程
sudo lsof -n -i4TCP:5672 | grep LISTEN
类似地,对于使用 IPv6 的程序
sudo lsof -n -i6TCP:5672 | grep LISTEN
在端口 1883 上
sudo lsof -n -i4TCP:1883 | grep LISTEN
sudo lsof -n -i6TCP:1883 | grep LISTEN
如果上述命令没有输出,则表示没有本地操作系统进程在给定端口上侦听。
以下示例使用ss
显示使用 IPv4 的侦听 TCP 套接字及其操作系统进程
sudo ss --tcp -f inet --listening --numeric --processes
类似地,对于使用 IPv6 的 TCP 套接字
sudo ss --tcp -f inet6 --listening --numeric --processes
有关 RabbitMQ 及其各种插件使用的端口列表,请参见上文。通常,用于外部连接的所有端口都必须由防火墙和代理允许。
rabbitmq-diagnostics listeners
和rabbitmq-diagnostics status
可用于列出 RabbitMQ 节点上启用的监听器及其端口。
IP 路由
RabbitMQ 支持的消息传递协议使用 TCP,并要求客户端和 RabbitMQ 主机之间存在 IP 路由才能正常工作。有几种工具和技术可用于验证两个主机之间的 IP 路由。traceroute和ping是许多操作系统提供的两个常见选项。大多数路由表检查工具是特定于操作系统的。
请注意,traceroute
和ping
都使用ICMP,而 RabbitMQ 客户端库和节点间连接使用 TCP。因此,仅成功运行ping
不能保证客户端连接成功。
traceroute
和ping
都有基于 Web 和 GUI 的工具构建在其之上。
捕获流量
所有网络活动都可以使用流量捕获进行检查、过滤和分析。
tcpdump 及其图形界面版本 Wireshark 是捕获、过滤和分析流量的行业标准。两者都支持 RabbitMQ 支持的所有协议。请参阅 使用 Wireshark 与 RabbitMQ 指南以获取概述。
TLS 连接
对于使用 TLS 的连接,有一个单独的 关于 TLS 故障排除的指南。
在采用 TLS 时,务必确保客户端使用正确的端口进行连接(请参见上面的端口列表),并指示它们使用 TLS(执行 TLS 升级)。未配置为使用 TLS 的客户端将成功连接到启用 TLS 的服务器端口,但其连接随后将超时,因为它从未执行服务器期望的 TLS 升级。
启用 TLS 的客户端连接到未启用 TLS 的端口将成功连接并尝试执行 TLS 升级,但服务器不希望这样做,这将触发协议解析器异常。服务器将记录此类异常。
检查连接
可以使用netstat、ss、lsof检查节点的开放端口、TCP 和 UDP 连接。
以下示例使用 netstat
列出所有 TCP 连接套接字,无论其状态和接口如何。IP 地址将显示为数字,而不是解析为域名。程序名称将打印在数字端口值旁边(而不是协议名称)。
sudo netstat --all --numeric --tcp --programs
可以通过这种方式检查入站(客户端、对等节点、CLI 工具)和出站(对等节点、联合链接和铲子)连接。
rabbitmqctl list_connections
、管理 UI 可用于检查更多连接属性,其中一些属性是 RabbitMQ 或消息协议特有的
- 网络流量流,包括入站和出站
- 使用的消息传递(应用程序级)协议
- 连接虚拟主机
- 连接时间
- 用户名
- 通道数
- 客户端库详细信息(名称、版本、功能)
- 有效心跳超时
- TLS 详细信息
将管理 UI 或 CLI 工具中的连接信息与 netstat
或 ss
的连接信息结合起来,可以帮助排除应用程序、应用程序实例和客户端库行为异常的问题。
可以使用 Prometheus 和 Grafana 收集、聚合和 监控 最相关的连接指标。
检测高连接抖动
高连接抖动(在短时间内打开和关闭大量连接)可能导致资源耗尽。因此,能够识别此类场景非常重要。netstat
和 ss
是 检查 TCP 连接 最受欢迎的选择。TIME_WAIT
状态下的大量连接是高连接抖动的可能症状。除 ESTABLISHED
之外的其他状态下的大量连接也可能值得调查。
在 RabbitMQ 日志文件中可以找到短暂连接的证据。例如,这是一个持续时间仅几毫秒的连接示例
2018-06-17 16:23:29.851 [info] <0.634.0> accepting AMQP connection <0.634.0> (127.0.0.1:58588 -> 127.0.0.1:5672)
2018-06-17 16:23:29.853 [info] <0.634.0> connection <0.634.0> (127.0.0.1:58588 -> 127.0.0.1:5672): user 'guest' authenticated and granted access to vhost '/'
2018-06-17 16:23:29.855 [info] <0.634.0> closing AMQP connection <0.634.0> (127.0.0.1:58588 -> 127.0.0.1:5672, vhost: '/', user: 'guest')