45

在 RabbitMQ/AMQP Java 客户端中,您可以创建一个AMQP.BasicProperties.Builder,并将其build()用于AMQP.BasicProperties. 然后可以将这个构建的属性实例用于各种重要的事情。这个构建器类有很多“构建器”风格的方法:

BasicProperties.Builder propsBuilder = new BasicProperties.Builder();
propsBuilder
    .appId(???)
    .clusterId(???)
    .contentEncoding(???)
    .contentType(???)
    .correlationId(???)
    .deliveryMode(2)
    .expiration(???)
    .headers(???)
    .messageId(???)
    .priority(???)
    .replyTo(???)
    .timestamp(???)
    .type(???)
    .userId(???);

我正在寻找这些构建器方法有助于“构建”的字段,最重要的是,每个字段存在哪些有效值。例如,什么是 a clusterId,它的有效值是什么?什么是type,它的有效值是什么?等等。

我花了整个上午的时间来冲刷:

在所有这些文档中,我找不到关于每个字段是什么以及它们的有效值是什么的明确定义(除了对什么和是的一些模糊解释)。有人知道吗?更重要的是,有人知道这些甚至记录在哪里吗?提前致谢!prioritycontentEncodingdeliveryMode

4

3 回答 3

83

通常我使用非常简单的方法来记忆一些东西。我将在下面提供所有详细信息,但这里是 BasicProperties 字段和值的简单图片。我还尝试正确突出显示队列/服务器和应用程序上下文。

在此处输入图像描述

如果您希望我对其进行一些改进-只需发表一个小评论。我真正想要的是提供一些视觉关键并简化理解。

高级描述来源 1来源 2):

请注意 Clust ID 已被弃用,因此我将其排除在外。

  • 应用程序 ID - 生成消息的应用程序的标识符。
    • 上下文:应用程序使用
    • 值:可以是任何字符串。
  • 内容编码- 消息内容编码
    • 上下文:应用程序使用
    • 值:MIME 内容编码(例如 gzip)
  • 内容类型- 消息内容类型
    • 上下文:应用程序使用
    • 值:MIME 内容类型(例如 application/json)
  • Correlation ID - 与此相关的消息,例如此消息是对什么请求的回复。鼓励应用程序使用此属性,而不是将此信息放入消息负载中。
    • 上下文:应用程序使用
    • 值:任何值
  • 传递模式- 消息是否应该持久化到磁盘?
    • 上下文:队列实现使用
    • 值:非持久性 (1) 或持久性 (2)
  • 过期- 邮件将被删除的过期时间。expire 字段的值以毫秒为单位描述 TTL 周期。请参阅下面的详细信息。
    • 上下文:队列实现使用
  • 标头- 任意特定于应用程序的消息标头。
    • 上下文:应用程序使用
  • 消息 ID - 字符串形式的消息标识符。如果应用程序需要识别消息,建议他们使用此属性而不是将其放入消息负载中。
    • 上下文:应用程序使用
    • 值:任何值
  • 优先级- 消息优先级。
    • 上下文:队列实现使用
    • 值:0 到 9
  • ReplyTo - 其他应用程序应将响应发送到的队列名称。通常用于命名回复队列(或任何其他帮助消费者应用程序指导其响应的标识符)。鼓励应用程序使用此属性,而不是将此信息放入消息负载中。
    • 上下文:应用程序使用
    • 值:任何值
  • 时间戳- 发送消息的时刻的时间戳。
    • 上下文:应用程序使用
    • 值:自纪元以来的秒数。
  • 类型- 消息类型,例如该消息代表什么类型的事件或命令。建议由应用程序使用,而不是将此信息包含在消息负载中。
    • 上下文:应用程序使用
    • 值:可以是任何字符串。
  • 用户 ID - 可选用户 ID。由 RabbitMQ 针对实际连接用户名进行验证。
    • 上下文:队列实现使用
    • 值:应该是经过身份验证的用户。

顺便说一句,我终于设法查看了最新的服务器代码(rabbitmq-server-3.1.5),rabbit_stomp_test_util.erl 中有一个示例:

                content_type     = <<"text/plain">>,
                content_encoding = <<"UTF-8">>,
                delivery_mode    = 2,
                priority         = 1,
                correlation_id   = <<"123">>,
                reply_to         = <<"something">>,
                expiration       = <<"my-expiration">>,
                message_id       = <<"M123">>,
                timestamp        = 123456,
                type             = <<"freshly-squeezed">>,
                user_id          = <<"joe">>,
                app_id           = <<"joe's app">>,
                headers          = [{<<"str">>, longstr, <<"foo">>},
                                    {<<"int">>, longstr, <<"123">>}]

很高兴知道有人想知道所有细节。因为在可能的情况下使用众所周知的消息属性比在消息正文中放置信息要好得多。顺便说一句,基本的消息属性远非清晰和有用。我会说最好使用自定义的。

在此处输入图像描述

好例子来源

在此处输入图像描述

更新 - 到期字段

重要提示:过期属于队列上下文。所以消息可能会被服务器丢弃。

在此处输入图像描述

自述文件说以下内容:

expiration是一个shortstr;由于 RabbitMQ 会期望这是一个编码字符串,我们将 a 转换ttl为它的整数值的字符串表示形式。

资料来源:

于 2013-08-26T15:12:35.150 回答
10

在撰写本文时:

  1. 最新的 AMQP 标准是AMQP 1.0 OASIS 标准
  2. RabbitMQ 的最新版本是 3.1.5(服务器和客户端),声称支持AMQP 0.9.1(pdf 和 XML 模式压缩)。
  3. RabbitMQ 将它自己的协议描述提供为XML 模式,包括扩展(即非标准),加上没有扩展的 XML 模式(与通过 (2) 链接的模式相同)和pdf doc

在这个答案中:

  • (3) 中的链接是详细信息的主要来源
  • (2) 如果 (3) 不充分,则使用 pdf doc 作为次要详细信息
  • 如果 (2) 不充分,则源代码(java 客户端、erlang 服务器)用作第三细节。
  • (1) 通常不使用 - 协议和模式已经(相当)为/由 OASIS 显着发展,应该适用于 RabbitMQ 的未来版本,但现在不适用。使用 (1) 的两个例外是用于和的文本描述contentType-contentEncoding这是安全的,因为这些是在 AMQP 1.0 中具有良好描述的标准字段。

下面的文字是我从这些来源中转述的,以使其更加简洁或清晰。

  • 内容类型(AMQP XML type="shortstr"; java type="String"):可选。消息的应用程序数据部分(正文)的 RFC-2046 MIME 类型。可以包含定义使用的字符编码的 charset 参数:例如,'text/plain; 字符集=“utf-8”'。如果内容类型未知,则不应设置内容类型,从而允许接收者确定实际类型。如果该部分是真正不透明的二进制数据,则内容类型应该设置为 application/octet-stream。
  • 内容编码(AMQP XML type="shortstr"; java type="String"):可选。当存在时,描述了应用于应用数据的附加内容编码,因此需要应用哪些解码机制才能获得内容类型头字段引用的媒体类型。主要用于允许压缩文档而不丢失其基础内容类型的标识。内容类型的修饰符,根据 RFC 2616 的第 3.5 节进行解释。有效的内容编码在 IANA 注册。实现不应该使用压缩编码,除非与最初使用其他协议(例如 HTTP 或 SMTP)发送的消息保持兼容。实现不应该指定多个内容编码值,除非与最初使用其他协议(例如 HTTP 或 SMTP)发送的消息兼容。
  • 标头(AMQP XML type="table"; java type="Map"):可选。应用程序指定的标头参数列表及其值。这些可以设置为仅供应用程序使用。此外,可以使用“标头交换类型”创建队列 - 创建队列时,会为其提供一系列标头属性名称以进行匹配,每个名称都有要匹配的可选值,以便通过标头路由到该队列-匹配。
  • deliveryMode (RabbitMQ XML type="octet"; java type="Integer"):1(非持久)或2(持久)。仅适用于实现持久性的队列。持久性消息安全地保存在磁盘上,即使出现严重的网络故障、服务器崩溃、溢出等情况,也能保证传送。
  • 优先级(AMQP XML type="octet"; java type="Integer"):相对消息优先级(0 到 9)。高优先级消息是 [MAY BE?? -GB] 在同一消息队列中等待的较低优先级消息之前发送。当必须丢弃消息以维持特定的服务质量级别时,服务器将首先丢弃低优先级消息。仅适用于实现优先级的队列。
  • 相关 ID(AMQP XML type="octet"; java type="String"):可选。对于应用程序使用,没有正式的 (RabbitMQ) 行为。一个特定于客户端的 id,可用于标记或识别客户端之间的消息。
  • replyTo (AMQP XML type="shortstr"; java type="String"):可选。对于应用程序使用,没有正式的 (RabbitMQ) 行为,但在请求消息中使用时可能包含私有响应队列的名称。要发送回复的节点的地址。
  • 过期(AMQP XML type="shortstr"; java type="String"):可选。(3) 中的RabbitMQ AMQP 0.9.1 模式声明“用于实现用途,没有正式行为”。(2) 中的 AMQP 0.9.1 模式 pdf 说明了此消息被视为过期的绝对时间。但是,必须忽略这两个描述,因为此 TTL 链接和客户端/服务器代码表明以下情况为真。从客户端,到期只能通过 BasicProperties 的自定义应用程序初始化来填充。在服务器上,这用于在排队之前从服务器接收到消息的那一刻起确定 TTL。服务器选择 TTL 作为 (1) 消息 TTL 的最小值(客户端BasicProperties 过期作为以毫秒为单位的相对时间)和(2)队列 TTL(以毫秒为单位配置的 x-message-ttl)。格式:字符串引用的整数,表示毫秒数;服务器收到消息的过期时间。
  • message-id (AMQP XML type="shortstr"; java type="String"):可选。对于应用程序使用,没有正式的 (RabbitMQ) 行为。如果设置,消息生产者应将其设置为全局唯一值。将来(AMQP 1.0),如果 message-id 的值与先前接收到的发送到同一节点的消息的值匹配,则代理可以将消息作为副本丢弃。
  • 时间戳(AMQP XML type="timestamp"; java type="java.util.Date"):可选。对于应用程序使用,没有正式的 (RabbitMQ) 行为。创建此消息的绝对时间。
  • 类型(AMQP XML type="shortstr"; java type="String"):可选。对于应用程序使用,没有正式的 (RabbitMQ) 行为。[将消息描述为/属于特定于应用程序的“类型”或“形式”或“业务交易”-GB]
  • userId (AMQP XML type="shortstr"; java type="String"):可选。XML Schema 声明“对于应用程序使用,没有正式的 (RabbitMQ) 行为”——但我相信这在最新版本中已经改变(继续阅读)。如果设置,客户端将此值设置为负责生成消息的用户的身份。来自RabbitMQ:如果此属性由发布者设置,则其值必须等于用于打开连接的用户的名称(即进行验证以确保它是已连接/经过身份验证的用户)。如果未设置 user-id 属性,则发布者的身份保持私有。
  • appId (RabbitMQ XML type="shortstr"; java type="String"):可选。对于应用程序使用,没有正式的 (RabbitMQ) 行为。创建应用程序 ID。可以由生产者填充并由消费者读取。(查看 R-MQ 服务器代码,服务器根本不使用它,尽管“webmachine-wrapper”插件提供了一个脚本和匹配的模板来创建一个 web 机器——管理员可以在其中为脚本提供一个 appId。)
  • 集群 ID (RabbitMQ XML type="N/A"; java type="String"):在 AMQP 0.9.1 中已弃用 - 即未使用。在以前的版本中,是集群内路由标识符,供集群应用程序使用,不应由客户端应用程序使用(即不填充)。但是,这已被弃用并从当前模式中删除,并且不被 R-MQ 服务器代码使用。

正如您在上面看到的,这些属性中的绝大多数都没有枚举/约束/推荐值,因为它们是“仅限应用程序使用”而不被 RabbitMQ 使用。所以你有一份轻松的工作。您可以自由地写入/读取对您的应用程序有用的值 - 只要它们匹配数据类型并编译 :)。 ContentTypecontentEncoding按照标准 HTTP 使用。 DeliveryMode并且priority是受约束的数字。

注意:AMQP.BasicProperties 有用但简单的常量在MessageProperties类中可用。

干杯:)

更新发布:

非常感谢 Renat(请参阅评论),查看了 rabbit_amqqueue_process.erl 中的 erlang 服务器代码和RabbitMQ TTL Extensions to AMQP中的文档。可以指定消息过期(生存时间)

  • 每个队列通过:

    Map<String, Object> args = new HashMap<String, Object>();
    args.put("x-message-ttl", 60000);
    channel.queueDeclare("myqueue", false, false, false, args);
    
  • 或通过以下方式发送消息:

    byte[] messageBodyBytes = "Hello, world!".getBytes();
    AMQP.BasicProperties properties = new AMQP.BasicProperties();
    properties.setExpiration("60000");
    channel.basicPublish("my-exchange", "routing-key", properties, messageBodyBytes);
    

在这里,ttl/expiration 以毫秒为单位,因此每种情况下为 60 秒。已更新上述到期定义以反映这一点。

于 2013-08-27T05:49:58.383 回答
0

AMQP规范定义了一个通用的、可扩展的属性模型。

AMQP 属性在概念上与 HTTP 标头有些相似,因为它们表示有关消息的元数据。就像在 HTTP 中一样,它们与消息负载分开构建。但它们基本上是一个键/值映射。

一些像 RabbitMQ 这样的代理会解释某些消息属性,比如expiration添加额外的供应商特定值(在这种情况下,强制执行 TTL)。

但归根结底,AMQP 属性只是一大堆键/值对,它们与每条消息一起安全发送,如果您选择这样做的话。您的 AMQP 代理的文档将告诉您他们专门解释哪些以及如何发送您自己的。

话虽如此,如果您首先提出这个问题,那么您可能根本不需要担心它们。您将能够成功发送消息,而无需担心设置任何消息属性。

于 2013-08-27T02:49:35.100 回答