问题是何时向代理发送确认字符
或NACK
帧。STOMP规范说:
确认字符用于使用客户端或客户端个体确认确认确认订阅消息的消费。在此类订阅中收到的任何消息在通过确认字符确认消息之前都不会被视为已消费。
“消费”对我来说意味着“接收和处理后”。所以我可以想象两种情况。
场景A收到消息后:
function on_message(message)
message.ack()
heavy_processing(message)
或消息处理后的场景B:
function on_message(message)
heavy_processing(message)
message.ack()
根据我的理解,NACK
是告诉代理,例如,这个侦听器被临时标记为非活动的。正如我所理解的,NACK
不是因为异常而将消息标记为未处理。
因此,根据我的理解,以下伪代码将正确处理确认字符
、NACK
和异常:
function on_message(message)
if online(): # checks resources etc
message.ack()
else:
message.nack()
return
try:
heavy_processing(message) # processing takes 5-10 minutes
catch Exception: # could be problem with this Listener or malformed message
message.put_to_dlq() # putting to dlq is a "manual" process
return
FYI我所说的系统是在Python3.7. x中构建的,带有Stomp.py模块和ActiveMQ。
正如您所说,“消费”意味着“收到并处理后”,当您成功处理消息时,您需要无一例外地确认消息。所以场景B将是合适的。
从留档
NACK与确认字符相反。它用于告诉服务器客户端没有使用该消息。
因此,在这种情况下NACK意味着您已收到消息,但未成功处理它。
注意:如果您为失败的消息(导致异常的消息)维护一个单独的队列,那么您可以将这些消息发布到另一个(在您的情况下为dlq队列
)并积极确认(确认字符)这些失败消息的原始队列。
STOMP规范是这样描述NACK
框架的:
NACK
与确认字符
相反。它用于告诉服务器客户端没有使用该消息。然后,服务器可以将消息发送到不同的客户端,丢弃它,或者将其放入死信队列中。确切的行为是特定于服务器的。
因此,一个NACK
帧告诉服务器客户端没有使用该消息,但它没有说明原因。
NACK
帧并不表示监听器以某种方式暂时标记为不活动。代理将继续向监听器发送消息(假设它是活动的)。
NACK
可以表示由于异常而未处理消息。同样,规范在这里没有区分情况。
NACK
产生的行为由服务器决定。