何时在 STOMP 中的队列侦听器上发送 ACK 或 NACK

When to send ACK or NACK on queue listener in STOMP

问题是何时将 ACKNACK 帧发送给代理。 STOMP specification 表示:

ACK is used to acknowledge consumption of a message from a subscription using client or client-individual acknowledgment. Any messages received from such a subscription will not be considered to have been consumed until the message has been acknowledged via an ACK.

"Consumption" 对我来说意味着 "after received and processed"。所以我可以想象两种情况。

场景A收到消息后:

function on_message(message)
    message.ack()
    heavy_processing(message)

或场景B消息处理后:

function on_message(message)
    heavy_processing(message)
    message.ack()

据我所知,NACK 是为了告诉经纪人,例如这个侦听器已被临时标记为不活动。正如我所理解的那样,NACK 不会因为异常而将消息标记为未处理。

因此,根据我的理解,以下伪代码将正确处理 ACKNACK 和异常:

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

仅供参考,我正在谈论的系统是在 Python 3.7.x 中构建的,带有 Stomp.py 模块和 ActiveMQ。

正如您所说,'Consumption' 意味着 'after received and processed',您需要在成功处理您的消息后确认消息,无一例外。因此,场景 B 将是合适的场景。

来自documentation

NACK is the opposite of ACK. It is used to tell the server that the client did not consume the message.

因此在此上下文中的 NACK 表示您已收到消息但未成功处理它。

注意:如果您为失败的消息(导致异常的消息)维护一个单独的队列,那么您可以将这些消息发布到另一个(dlq queue 在您的case) 并积极确认 (ACK) 到那些失败消息的原始队列。

STOMP specification 关于 NACK 框架的说法:

NACK is the opposite of ACK. It is used to tell the server that the client did not consume the message. The server can then either send the message to a different client, discard it, or put it in a dead letter queue. The exact behavior is server specific.

所以一个 NACK 帧告诉服务器客户端没有使用该消息,但是 它不表示 为什么

一个 NACK 表示侦听器以某种方式暂时标记为不活动。代理将继续向侦听器发送消息(假设它处于活动状态)。

A NACK 可能 表示由于异常而未处理邮件。同样,规范在这里没有区分大小写。

NACK 的结果行为由服务器决定。