我们将NServiceBus 6与MSMQ和RabbitMq一起使用。当我们使用带有分布式事务的MSMQ时,我们从来没有比提交分布式事务更早地调度消息。但是,当我们将其关闭并手动将其包装在事务范围内时,我们看到Nsb在处理程序执行结束之前就开始发送消息。我们的代码如下:
public Task Handle(ICommand1 message, IMessageHandlerContext context)
{
using (var tx = _session.BeginTransaction(IsolationLevel.ReadCommitted))
{
HandleMessage1(message1);
_session.Flush();
tx.Commit();
}
}
private void HandleMessage1(ICommand1 message1)
{
// Updating database
...
// Sending other Command2 to separate handler
bus.Send<ICommand2>(x =>
{
...
});
}
从日志中,我可以看到ICommand2开始处理的时间比ICommand1处理程序设法处理的要早,因为ICommand1处理程序在提交Command1处理程序的数据更新之前,先提交数据库中的数据更改,获取“旧”数据。
由于Nsb6为我们提供了Batched message dispatch,因此我对我们不会遇到此类问题感到印象深刻。看来这不是我们的情况,我想知道为什么以及如何解决该问题。我试图在MSMQ(无分布式事务)和RabbitMq下运行它,结果是相同的。
Command2处理程序可处理Command1处理程序所做的更改,那么如何使它们顺序工作?
答案 0 :(得分:2)
应使用传递到处理程序中的context
完成从处理程序中发送消息。使用bus.Send()
时,您可能会使用IMessageSession
而不是IMessageHandlerContext
,这等效于立即分发。
将代码更改为以下内容即可解决该问题:
public async Task Handle(ICommand1 message, IMessageHandlerContext context)
{
using (var tx = _session.BeginTransaction(IsolationLevel.ReadCommitted))
{
await HandleMessage1(message1, context);
_session.Flush();
tx.Commit();
}
}
private async Task HandleMessage1(ICommand1 message1, IMessageHandlerContext context)
{
// Updating database
...
// Sending other Command2 to separate handler
await context.Send<ICommand2>(x =>
{
...
});
}