跳到主要内容
版本: 4.1

RabbitMQ URI 规范

概述

本规范定义了一个 “amqp” URI 方案。符合规范的 URI 表示 AMQP 0-9-1 客户端以及一些 RabbitMQ 插件连接到 RabbitMQ 节点所需的信息。

简介

本规范的范围仅限于 AMQP 0-9-1,这是 RabbitMQ 实现的原始协议。AMQP 0-9-1 客户端连接到 RabbitMQ 节点,以便根据消息模型发布和消费消息。

客户端需要若干信息来建立和协商 AMQP 0-9-1 连接。这些连接参数包括

  • 建立与服务器的底层 TCP/IP 连接所需的参数(即主机地址和端口)。

  • 用于验证客户端身份的信息。AMQP 0-9-1 使用 SASL 进行身份验证。通常使用 PLAIN 机制,因此身份验证参数包括用户名和密码。

  • “虚拟主机”(或 vhost)的名称,它指定协议引用的实体(例如交换机和队列)的命名空间。请注意,这与 HTTP 意义上的虚拟主机不同。

RabbitMQ 客户端通常会从配置文件或环境变量中获取所有这些参数,以便设置连接。因此,如果可以将连接参数组合成一个字符串,而不是作为不同的配置设置,那将非常方便。这意味着只需要一个配置设置,并且只需要将一个值传递给客户端库。

但是,将连接参数组合成一个字符串需要一个约定,客户端库需要理解连接参数是如何表示和分隔的。最好将该约定标准化,以便许多 AMQP 0-9-1 客户端库可以一致地实现它。这种标准的显而易见的基础是在 RFC3986 中定义的 URI 的通用语法。

本规范的目的是定义 “amqp” 和 “amqps” URI 方案,它们在通用 URI 语法中表示 AMQP 0-9-1 连接参数。

“amqp” URI 方案

AMQP 0-9-1 URI 的语法由以下 ABNF 规则定义。这些规则中所有未在此处定义的名称均取自 RFC3986

amqp_URI       = "amqp://" amqp_authority [ "/" vhost ] [ "?" query ]

amqp_authority = [ amqp_userinfo "@" ] host [ ":" port ]

amqp_userinfo = username [ ":" password ]

username = *( unreserved / pct-encoded / sub-delims )

password = *( unreserved / pct-encoded / sub-delims )

vhost = segment

一旦 URI 根据此语法成功解析,连接参数将按照以下部分中的描述确定。

主机

底层 TCP 连接所连接的主机根据 RFC3986 第 3.2.2 节中的主机组件确定。请注意,根据 ABNF,主机组件可能不会缺失,但可以是零长度。

端口

底层 TCP 连接所连接的端口号根据 RFC3986 中的端口组件确定。端口组件可能缺失,表现为缺少将端口与主机分隔开的 “:” 字符。如果端口组件缺失,则应替换为 IANA 分配的 AMQP 0-9-1 端口号 5672。

用户名和密码

如果存在,则应在通过 connection.secureconnection.secure-ok AMQP 0-9-1 方法发生的 SASL 交换中使用用户名和密码组件。用户名和密码中任何百分比编码的八位字节都应在 SASL 交换中使用之前解码,并且生成的八位字节序列应被视为 UTF-8 编码。

用户名和密码都可能缺失;它们的缺失通过缺少将 amqp_userinfo 与主机分隔开的 “@” 字符来表示。如果用户名存在,则密码可能缺失;这通过缺少将密码与用户名分隔开的 “:” 字符来表示。零长度的用户名和密码与缺失的用户名和密码不等效。

RFC3986 规定 “用户信息的组件中出现的密码已被弃用,应被视为错误”(第 7.5 节)。虽然这在面向用户的应用程序(例如 Web 浏览器)以及可能不安全地存储和显示的 URI 的上下文中是合理的建议,但对于后端应用程序而言,这不一定有效。这些应用程序中的许多都是 “无头” 服务,并且代表整个应用程序而不是特定用户打开 RabbitMQ 连接。因此,用户名和密码标识的是应用程序而不是人类用户,并且很可能与配置设置的安全存储中出现的连接参数一起包含在内。面向用户的应用程序(代表特定用户建立 RabbitMQ 连接)也是可能的。在这种情况下,用户名和密码可以由用户提供以识别自己的身份。但是,此类应用程序是例外而不是规则。因此,实现此规范的应用程序的作者不应认为自己受 RFC3986 第 7.5 节的约束。另请参阅下面的 “安全注意事项” 部分。

虚拟主机

虚拟主机 (vhost) 组件用作 connection.open AMQP 0-9-1 方法的 virtual-host 字段的基础。vhost 中任何百分比编码的八位字节都应在传递到服务器之前解码。

请注意

  • URI 的 vhost 组件不包括路径中的前导 “/” 字符。这使得可以引用任何 vhost,而不仅仅是那些以 “/” 字符开头的 vhost。
  • vhost 是一个单独的段。因此,vhost 名称中出现的任何 “/” 字符都必须进行百分比编码。具有多段路径的 URI 不符合此规范。

vhost 组件可能缺失;这通过缺少 amqp_authority 后面的 “/” 字符来表示。缺失的 vhost 组件与空(即零长度)vhost 名称不等效。

处理缺失的组件

某些 URI 组件(端口、用户名、密码、vhost 和查询)可能在 URI 中缺失。主机可能不会缺失,但可以是零长度;就本节而言,零长度主机被视为缺失。

除了端口(在上面的 2.2 节中介绍)之外,本规范不强制规定实现应如何处理缺失的组件。可能的方法包括但不限于以下几种

  • 缺失的组件可以用默认值替换。
  • 面向用户的应用程序可能会提示用户提供缺失组件的值。
  • 缺失的组件可能会导致错误。

此外,应用程序可以针对不同的组件采用不同的策略。

例如,URI “amqp://”,其中所有组件都缺失,可能会导致客户端库使用一组默认值,这些默认值对应于连接到本地 RabbitMQ 服务器,并以访客用户身份进行身份验证。这对于开发目的来说会很方便。

“amqps” URI 方案

“amqps” URI 方案用于指示客户端与服务器建立安全连接。

AMQP 0-9-1 规范假设底层传输层提供可靠的面向字节流的虚拟电路。当不需要保护网络上的流量安全时,通常使用 TCP/IP 连接。

在必须保护流量安全的情况下,可以使用 TLS(请参阅 RFC5246)。当前的实践是将 AMQP 0-9-1 简单地分层在 TLS 之上以形成 “AMQPS”(类似于 HTTPS 将 HTTP 分层在 TLS 之上的方式)。AMQP 0-9-1 没有提供将非安全连接升级为安全连接的方法。因此,支持安全和非安全连接的服务器必须监听不同端口以处理这两种类型的连接。

除了方案标识符之外,“amqps” URI 方案的语法与 “amqp” URI 方案的语法相同

amqps_URI      = "amqps://" amqp_authority [ "/" vhost ]

amqps URI 的解释与相应的 “plain” URI 在两个方面有所不同。在所有其他方面,解释是相同的。

  • 客户端必须充当 TLS 客户端,并在建立底层 TCP/IP 连接后立即开始 TLS 握手。所有 AMQP 0-9-1 协议数据都作为 TLS “应用数据” 发送。除此之外,遵循正常的 AMQP 0-9-1 行为。
  • 如果 URI 中缺少端口号,则应使用 IANA 分配的 “amqps” 端口号 5671。

安全注意事项

如上面的 2.3 节所述,URI 通常会作为配置设置提供给应用程序。在这种情况下,如果密码无法合并到 URI 中,则它将仅作为单独的配置设置提供。这降低了使用 URI 的好处,而没有增加任何安全性。因此,本规范覆盖了 RFC3986 对用户信息组件中密码的弃用。

只要不影响安全性,开发人员可以随意使用密码组件。尽管如此,他们应该意识到密码组件的内容可能很敏感,并且应该避免泄漏它(例如,完整的 URI 不应出现在异常消息或日志记录中,这些消息或日志记录可能对权限较低的人员可见)。

附录 A:示例

下面是一个示例表格,展示了应如何根据本规范解析 URI。这些示例中的许多示例旨在演示边缘情况,以便阐明规范并为解析 URI 的代码提供测试用例。每行显示一个 URI,以及每个组件生成的八位字节序列。这些八位字节序列用双引号括起来。空单元格表示缺失的组件,如第 3 节中所述。

URI用户名密码主机端口虚拟主机
amqp://user:pass@host:10000/vhost"user""pass""host"10000"vhost"
amqp://user:passw%23rd@host:10000/vhost"user""passw#rd""host"10000"vhost"
amqp://user%61:%61pass@ho%61st:10000/v%2fhost"usera""apass""hoast"10000"v/host"
amqp://
amqp://:@/""""""
amqp://user@"user"
amqp://user:pass@"user""pass"
amqp://host"host"
amqp://:1000010000
amqp:///vhost"vhost"
amqp://host/"host"""
amqp://host/%2f"host""/"
amqp://[::1]"[::1]" (即 IPv6 地址 ::1)

附录 B:查询参数

客户端可能需要进一步的参数化来定义它们应如何连接到服务器。可以使用标准 URI 查询语法为客户端提供其他信息。

查询参数可能比其他 URI 部分更具特定于实现的特性;因此,本文档不会尝试规定应如何使用它们。但是,我们已经记录了 官方支持的客户端如何读取 URI 查询参数

© . All rights reserved.