JMSMessageID 是否应该在发布和订阅之间更改?

Should the JMSMessageID change between publish and subscribe?

JMS 2.0 规范说

The JMSMessageID header field contains a value that uniquely identifies each message sent by a provider.

...和...

The exact scope of uniqueness is provider defined. It should at least cover all messages for a specific installation of a provider where an installation is some connected set of message routers.

规范没有明确规定从发布 API 调用返回的 JMSMessageID 必须与使用消息时出现的消息匹配。规范中关于在回复请求时将 JMSMessageID 移动到 JMSCorrelationID 的讨论暗示两者是相同的。如果消息 ID 在发布和消费之间发生了变化,这种 request/reply 的样式将失败。

当然,在 JMS 1.1 和现在的 2.0 的统一域模型中,JMSMessageID 的行为根据目标是队列还是主题而改变是没有意义的。在统一模型下,人们会期望所有目的地在这方面都表现相似。

此外,如果第一段中使用的 "provider" 指的是正在发送消息的事物,那么一个散布为 10 条具有相同 JMSMessageID 值的相同消息的发布将满足规范,因为唯一性是在发送方测量的。

不幸的是,该规范在使用术语 "provider" 来描述发送消息的事物与使用它来描述 JMS 传输供应商之间自由切换。这在上面引用的两个段落中很明显。这种歧义对任何事情都没有帮助。

至少有一个实现(IBM 的 MQ)采用了这样一种方法,即一个散布为 10 条消息的发布创建了 10 条唯一的新消息,因此每条消息都有一个唯一的 JMSMessageID 值。这可以说与第二个引用的段落一致,该段落要求在提供者范围内具有唯一性,其中 "provider" 似乎指的是供应商实现, 而不是 发送消息的东西。

我相信,当一条已发布的消息散布到多个订阅者时,正确的行为是 JMSMessageID 将保留在消息的每个实例中,以便可以按预期关联回复。换句话说,我认为 IBM 的实施是不合规的。由于规范在这个问题上模棱两可,我正在寻找一个权威来源,它要么以一种方式或另一种方式直接说明或强烈暗示规范所预期的行为。根据响应,我要么退出,要么将问题作为合规性缺陷向 IBM 提出。

这里的术语 "provider" 只是对正在使用的特定消息传递产品的引用,涵盖了 client-side 和 server-side 组件。为避免混淆,我将在此处使用 JMS 产品供应商一词。

JMS 规范的目的是定义由该消息产品实现的 Java API。它使用像 "provider" 这样的宽松术语,因为 JMS 规范没有定义产品的架构方式,并且试图避免建议如何在 client-side 和 server-side 组件之间共享实现,甚至是否有服务器(或服务器集群)。您会注意到规范从不(好吧,几乎从不)说 "the server does this" 或 "the server does that"。

关于 "exact scope of uniqueness" 的句子是为了让 JMS 产品供应商更容易实现生成 JMSMessageID 值的代码。它是说生成 JMSMessageID 值的代码不需要担心确保生成的值在整个宇宙中是唯一的。确保它们对于特定产品安装是唯一的就足够了。

你说 "The specification does not explicitly state that the JMSMessageID returned from the publish API call must match the one present in the message when it is consumed."

我认为这在第 4.4.11 节中有说明"How message header values are set"。这表示 JMSMessageID 由 "JMS provider send method" 设置。同一部分继续说 "Message header fields that are defined as being set by the 'JMS provider send method' will be available on the sending client as well as on the receiving client."

这意味着在对 send() 或 publish() 的调用返回后,发送应用程序可以使用方法 getJMSMessageID() 来查找分配给该消息的消息 ID。收到此消息时,接收应用程序可以使用相同的方法,并获得相同的值。

发送到某个主题的每条消息都会传递给该主题的每个订阅者。这些订阅者将收到同一消息的单独副本,具有相同的 body、属性和 headers,包括 JMSMessageID 值。

欢迎讨论; JMS 规范并非没有歧义。

我认为这里的问题不是关于何时在已发布的消息上设置 JMSMessageID 字段,而是更多关于在 JMS 提供程序中处理该消息时会发生什么。

如 T.Rob 和 Nigel 的帖子所述,JMS 2.0 规范的第 3.4.3 节指出:

"The JMSMessageID header field contains a value that uniquely identifies each message sent by a provider."

还有:

"A JMSMessageID is a String value which should function as a unique key for identifying messages in a historical repository. The exact scope of uniqueness is provider defined. It should at least cover all messages for a specific installation of a provider where an installation is some connected set of message routers."

也就是说,两个或多个消息,即使它们包含相同的数据,如果它们在存储库中构成不同的消息,也应该具有不同的 JMSMessageID 值。

该规范还在第 4.2.1 节中指出,

"A topic can be thought of as a mini message broker that gathers and distributes messages addressed to it. By relying on the topic as an intermediary, message publishers are kept independent of subscribers and vice versa."

这意味着规范的意图是,当消息被发送到主题时,主题可以对消息做一些工作,包括创建消息的多个副本(或者更具体地说,创建具有相同数据的多条消息在提供商的存储库中被认为是独立的。

最后,第 4.2.2 节指出:

"A subscription will receive a copy of every message that is sent to the topic after the subscription is created, ... Each copy of the message is treated as a completely separate message. Work done on one copy has no effect on any other; acknowledging one does not acknowledge any other; one message may be delivered immediately, while another waits for its consumer to process messages ahead of it."

将这些段落放在一起,规范可以理解为

  1. 将消息发送到主题时,该主题可以为每个当前订阅创建消息的副本。
  2. 发送到主题时创建的消息副本可以被视为完全独立的消息。
  3. 因为单独的 JMS 消息由它们的 JMSMessageID 字段唯一标识,所以每个单独的订阅消息都应该有不同的 JMSMessageID

接下 Nigel 的最后一句话,JMS 规范并非没有歧义。这是非常正确的,供应商和客户之前已经解决了问题,并且专家组的工作确实在澄清这些问题并提供指导以及提出改进合规性测试的建议。基于上述理解以及 IBM MQ v8 通过的 JMS 2.0 合规性测试套件中的测试,IBM MQ v8 实现符合 JMS2.0(并且同样早期的 IBM MQ 版本符合 JMS1.1;JMS 1.1 规范具有相同的歧义)。

请求-响应范式是一种常见的范式,尽管使用基于发布-订阅的分发模型,发送应用程序可能必须处理多个响应,而不仅仅是点对点体系结构中更可能出现的响应.我们承认,在某些消息传递场景中,消息 id 具有不同于 IBM MQ 当前实现的 'value of uniqueness' 的能力将为某些 IBM MQ 客户提供价值

由于上述原因,IBM 坚信其 MQ JMS 解决方案是合规的,因此不会接受 PMR。但是,我们承认在许多用例中维护消息 ID 对您是有益的。出于这个原因,我们将 RFE 35062 列为未提交的候选者,这意味着它最有可能得到解决,我们承诺我们正在积极努力,尽快提供最适合需求的解决方案。但要做到这一点,我们希望对 RFE 提供更多反馈,并说明我们的用户在这里试图解决的实际问题。例如,这是出于审计目的、请求-回复、消息流等,您需要复制什么?我们掌握的信息越多,解决方案就越有可能满足需求。