Qpid Proton Python release(delivered=True)在ActiveMQ Artemis中不触发重投计数
Apache ActiveMQ Artemis 2.40.0 + Qpid Proton Python 0.39.0:软NACK后消息无限重投,无法触发max-delivery-attempts
环境与需求
- 消息代理:Apache ActiveMQ Artemis 2.40.0
- AMQP客户端:Qpid Proton Python 0.39.0(python-qpid-proton)
- 核心需求:通过客户端软NACK操作,让消息按照broker配置的
max-delivery-attempts(5次)和redelivery-delay(5秒)重投,超过次数后自动进入死信队列(DLQ)
已配置的broker.xml地址规则
在broker.xml中配置全局地址规则:
<address-setting match="#"> <expiry-address>ExpiryQueue</expiry-address> <dead-letter-address>DLQ</dead-letter-address> <auto-create-dead-letter-resources>true</auto-create-dead-letter-resources> <dead-letter-queue-prefix></dead-letter-queue-prefix> <dead-letter-queue-suffix>.DLQ</dead-letter-queue-suffix> <max-delivery-attempts>5</max-delivery-attempts> <redelivery-delay>5000</redelivery-delay> </address-setting>
初始消费者代码
消费者尝试用release(delivered=True)实现软NACK的on_message逻辑:
def on_message(self, event): message = event.message status = send_message_callback(self.enrollment["target_url"], message.body) if 200 <= status < 300: self.accept(event.delivery) else: # Explicitly NACK the message self.release(event.delivery, delivered=True)
问题现象
- 调用
release(delivered=True)后,Artemis无限重投消息,完全不统计投递次数到max-delivery-attempts配置值 - 使用
reject(event.delivery)会直接将消息送入DLQ,不符合“先重投再进DLQ”的需求 - 尝试添加
<persist-delivery-count-before-delivery>标签到broker.xml,但该标签破坏Artemis 2.40.0的schema,导致服务无法启动 - Qpid Proton的
on_released、on_settled、on_rejected回调均未触发
解决方案:修正后的消费者代码
需在结算消息前手动更新本地投递状态,明确标记消息投递失败但仍可重新投递,再用MODIFIED状态完成结算。修正后的代码如下:
def on_message(self, event): message = event.message status = send_message_callback(self.enrollment["target_url"], message.body) if 200 <= status < 300: self.accept(event.delivery) else: # Explicitly NACK the message with proper state update local_state = event.delivery.local local_state.failed = True local_state.undeliverable = False event.delivery.update(local_state.type) self.settle(event.delivery, event.delivery.MODIFIED)
逻辑说明
failed=True:告知broker本次投递失败,需要递增投递次数undeliverable=False:告知broker消息仍可再次投递,不会直接进入DLQ- 用
MODIFIED状态结算后,Artemis会正确遵循配置的重投延迟和最大投递次数限制,超过次数后自动将消息转入DLQ
内容的提问来源于stack exchange,提问作者Daniel Nascimento
相关产品推荐
相关产品推荐

