我们使用 Rebus 作为带有 Sql server 的队列系统。对于不同类型的消息,我们有多个收件人。每条消息都可以由特定类型的多个工作人员处理。 一条消息只能由一名 worker 处理/处理(第一个拉出它的 worker )。如果工作人员由于某种原因无法完成它,它会使用超时服务推迟消息。
如果我没理解错的话,它就变成了一个TimeoutRequest,放在 超时表。当需要重新运行时,它会变成 TimeoutReply,然后再作为原始消息重新引入队列。
我们遇到的问题是,当它变成 TimeoutReply 时,所有工作人员都会选择它并创建原始消息。超时时,一条原始消息会变成多条消息(与工作人员一样多)。
我们的 Rebus 设置如下:
“服务器端”:
var adapter = new BuiltinContainerAdapter();
Configure.With(adapter)
.Logging(l => l.Log4Net())
.Transport(t => t.UseSqlServerInOneWayClientMode(connectionString).EnsureTableIsCreated())
.CreateBus()
.Start();
return adapter;
“ worker 端”:
_adapter = new BuiltinContainerAdapter();
Configure.With(_adapter)
.Logging(l => l.Log4Net())
.Transport(t => t.UseSqlServer(_connectionString, _inputQueue, "error")
.EnsureTableIsCreated())
.Events(x => x.AfterMessage += ((bus, exception, message) => SendWorkerFinishedJob(exception, message)))
.Events(x => x.BeforeMessage += (bus, message) => SignalWorkerStartedJob(message))
.Behavior(x => x.SetMaxRetriesFor<Exception>(0))
.Timeouts(x => x.StoreInSqlServer(_connectionString, "timeouts").EnsureTableIsCreated())
.CreateBus().Start(numberOfWorkers);
非常感谢任何帮助解决问题或提供理解的帮助!
最佳答案
我能想象到为什么您最终会收到多个超时回复的唯一原因是因为每个工作人员都充当超时管理器,并且他们似乎共享相同的存储空间。
这样,由于超时管理器在查询到期超时时不使用任何类型的锁定或任何东西,它们最终可能会抢夺相同的到期超时,这反过来会导致多个超时回复 - iow 存在竞争条件,但它没有被注意到,因为 this SQL不会注意到一行是否真的被删除了)。
我建议您 a) 为工作人员使用单独的超时表(例如 _inputQueue + ".timeouts"
),或者 b) 让所有工作人员使用外部超时管理器(即省略Timeouts(x => ...)
并启动一个独立的专用超时管理器。
在您的场景中,我猜 (a) 是最简单的方法,因为它非常接近您现在所拥有的。
不过我更喜欢 (b) 我自己,通常每台托管 Rebus 端点的机器都有一个超时管理器。
如果这能解决您的问题,请告诉我。
此外,我很想知道 SQL 传输如何为您工作:)
关于c# - 当超时时,我们如何避免多个 Rebus 消息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24263469/