网络连接故障排除
概述
本指南是 关于网络的指南 的补充,重点介绍网络连接的故障排除。
对于使用 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 监听器
- 节点间 和 CLI 工具 在端口
25672
上的通信 - AMQP 0-9-1(以及 1.0,如果启用)监听器,用于端口
5672
上的非 TLS 连接 - AMQP 0-9-1(以及 1.0,如果启用)监听器,用于端口
5671
上的 TLS 连接 - HTTP API 监听器,端口为 15672 (HTTP) 和 15671 (HTTPS)
- MQTT 监听器,用于非 TLS 连接 1883
在第二个示例中,节点上有 4 个 TCP 监听器
- 节点间 和 CLI 工具 在端口
25672
上的通信 - AMQP 0-9-1(以及 1.0,如果启用)监听器,用于非 TLS 连接,
5672
- AMQP 0-9-1(以及 1.0,如果启用)监听器,用于 TLS 连接,
5671
- HTTP API 监听器,端口为 15672(仅 HTTP)
所有监听器都绑定到所有可用的接口。
检查节点使用的 TCP 监听器有助于发现非标准端口配置、本应配置但未配置的协议插件(例如 MQTT)、节点仅限于少数网络接口的情况等等。 如果端口不在监听器列表中,则意味着节点无法接受其上的任何连接。
检查服务器日志
RabbitMQ 节点将 记录 关键客户端 连接生命周期事件。 必须成功建立 TCP 连接,并且对等方必须至少发送 1 个字节的数据,连接才会被视为(并记录为)已接受。
从此时开始,连接握手和协商按照所使用的消息传递协议的规范进行,例如 AMQP 0-9-1、AMQP 1.0 或 MQTT。
如果没有记录任何事件,则意味着要么没有成功的入站 TCP 连接,要么它们没有发送任何数据。
主机名解析
应用程序在连接到 RabbitMQ 时使用主机名或带有主机名的 URI 非常常见。 dig 和 nslookup 是用于解决主机名解析问题的常用工具。
端口访问
除了主机名解析和 IP 路由问题外,外部连接无法访问 TCP 端口是客户端连接失败的常见原因。 telnet 是一种常用的、非常简约的工具,用于测试到特定主机名和端口的 TCP 连接。
以下示例使用 telnet
连接到主机 localhost
的端口 5672
。 在 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
退出。
以下示例连接到 localhost
的端口 5673
。 连接失败(被操作系统拒绝),因为没有进程在该端口上监听。
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 系统上常用的防火墙。 Web 上不乏 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 及其 GUI 同级产品 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 工具)和出站(对等节点、Federation 链接和 Shovels)连接都可以通过这种方式进行检查。
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')