Solace未按JMS规范确认历史消息?是否违反JMS 1.1标准?
你完全没有遗漏什么,这也不是Solace违反了JMS规范——问题出在你使用的是Solace自定义的客户端确认模式,而不是JMS标准的CLIENT_ACKNOWLEDGE模式。
先明确JMS 1.1的规范要求:
JMS 1.1规范第4.4.11节规定:“确认一条已消费的消息时,会自动确认该会话已交付的所有消息。”
这确实是JMS标准CLIENT_ACKNOWLEDGE模式的核心行为:当你调用某条消息的acknowledge()方法时,该会话中所有之前已交付但未确认的消息都会被一次性确认。
但你代码里创建会话时用的是Solace的扩展属性SupportedProperty.SOL_CLIENT_ACKNOWLEDGE:
QueueSession queueSession = queueConnection.createQueueSession(false, SupportedProperty.SOL_CLIENT_ACKNOWLEDGE);
这个模式是Solace专门提供的单条消息确认模式,它的行为和标准JMS完全不同:调用某条消息的acknowledge()只会确认这条消息本身,其他已交付但未被显式确认的消息会保留在队列中,等待后续重新投递或者被确认。这就是为什么你的测试里偶数编号的消息还留在队列里的原因——你只确认了奇数消息,偶数消息从未被显式确认,所以不会被自动确认。
如果想要符合JMS规范的批量确认行为,只需要把会话创建的确认模式改成JMS标准的Session.CLIENT_ACKNOWLEDGE即可:
import javax.jms.Session; // ... QueueSession queueSession = queueConnection.createQueueSession(false, Session.CLIENT_ACKNOWLEDGE);
这样当你确认任意一条奇数消息时,该会话中之前所有已交付的消息(包括偶数消息)都会被自动确认,不会再留在队列里。
Solace提供这个自定义模式的初衷是为了满足更细粒度的消息确认需求——有些场景下用户需要精准控制每条消息的确认状态,而不是批量确认所有已交付的消息,这个扩展模式就很好地支持了这类场景。
内容的提问来源于stack exchange,提问作者Dan R.

