You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Wolverine+PostgreSQL时,死信重放后发送端而非消费端处理消息的问题

问题解决:Wolverine死信重放后发送端处理消息而非消费端

问题核心

使用Wolverine搭配PostgreSQL作为消息代理,发布者与消费者分属两个独立应用。正常情况下消息流转无问题,但消费者处理失败导致消息进入死信表,标记重放后,出现发送端(而非消费端)尝试处理这些消息的异常。

根因分析

发送端与消费端共享同一个PostgreSQL schema,且发送端启用了PersistMessagesWithPostgresql。Wolverine默认会让所有连接到同一消息存储的节点参与消息调度与处理,发送端的后台任务会拾取到重放的消息,误以为是需要自身处理的任务。

解决方案

1. 发送端配置:禁用本地消息处理,明确节点标识

修改发送端的Wolverine配置,禁止其处理任何入站消息,并设置唯一节点ID避免与消费端混淆:

builder.Host.UseWolverine(opts =>
{
    opts.NodeId = "publisher-node"; // 设置唯一节点标识
    opts.DisableAllLocalQueueProcessing(); // 完全禁用发送端的消息处理能力
    opts.PersistMessagesWithPostgresql(connectionString, "my-schema");
    opts.PublishMessage<MakeDocument>().ToPostgresqlQueue("my-queue");
});

2. 消费端配置:明确死信重放的处理权限

在消费端配置中,指定仅由消费端处理目标队列的死信重放,避免发送端干扰:

return builder.UseWolverine(opts =>
{
    opts.NodeId = "consumer-node"; // 设置唯一节点标识
    opts.PersistMessagesWithPostgresql(connectionString, "my-schema");
    opts.ListenToPostgresqlQueue("my-queue")
        .DeadLetterQueue(q => q.ReplayOnStartup()); // 仅消费端处理该队列的死信重放
    opts.OnException<ConcurrencyException>()
             .RetryOnce()
             .Then.RetryWithCooldown(TimeSpan.FromMilliseconds(100), TimeSpan.FromMilliseconds(250))
             .Then.MoveToErrorQueue();
});

3. 验证死信消息的目标路由

重放死信前,检查wolverine-dead-letters表中消息的destination字段,确保其值为my-queue,保证消息重放后会被正确路由到消费端监听的队列。

内容的提问来源于stack exchange,提问作者Farshad Shahsavari

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.11 22:13:14