Azure 操作需要时间时重试的消息
我有一个使用Azure ServiceBus的消息传递系统,但除此之外我还使用了Nimbus。我有一个端点,它向另一个端点发送命令,另一端的处理程序类在某一点接收命令,所以一切正常 当操作需要时间时,大约超过20秒左右,处理程序会收到带有相同消息的“另一个”调用。看起来Nimbus正在重试处理程序的另一个(甚至是同一个)实例已经在处理的消息,我没有看到任何异常被抛出,我可以使用以下处理程序轻松地重新编程:Azure 操作需要时间时重试的消息,azure,azureservicebus,nimbus,Azure,Azureservicebus,Nimbus,我有一个使用Azure ServiceBus的消息传递系统,但除此之外我还使用了Nimbus。我有一个端点,它向另一个端点发送命令,另一端的处理程序类在某一点接收命令,所以一切正常 当操作需要时间时,大约超过20秒左右,处理程序会收到带有相同消息的“另一个”调用。看起来Nimbus正在重试处理程序的另一个(甚至是同一个)实例已经在处理的消息,我没有看到任何异常被抛出,我可以使用以下处理程序轻松地重新编程: public class Synchronizer : IHandleCommand<
public class Synchronizer : IHandleCommand<RequestSynchronization>
{
public async Task Handle(RequestSynchronization synchronizeInfo)
{
Console.WriteLine("Received Synchronization");
await Task.Delay(TimeSpan.FromSeconds(30)); //Simulate long running process
Console.WriteLine("Got through first timeout");
await Task.Delay(TimeSpan.FromSeconds(30)); //Simulate another long running process
Console.WriteLine("Got through second timeout");
}
}
公共类同步器:IHandleCommand
{
公共异步任务句柄(RequestSynchronization synchronizeInfo)
{
Console.WriteLine(“接收到的同步”);
wait Task.Delay(TimeSpan.FromSeconds(30));//模拟长时间运行的进程
WriteLine(“通过第一次超时”);
wait Task.Delay(TimeSpan.FromSeconds(30));//模拟另一个长时间运行的进程
WriteLine(“通过第二次超时”);
}
}
我的问题是:如何禁用此行为?我很高兴交易需要时间,因为这是一个繁重的过程,我已经从我的网站上卸载了,这是使用这种架构的第一点
换句话说,我希望在另一个处理程序已经拾取并正在处理该消息时,该消息不会被另一个处理程序拾取,除非出现异常,该消息返回队列并最终被拾取以进行重试
有什么办法吗?我遗漏了什么吗?我想您正在这里寻找代码:默认情况下,ASB/WSB会给您30秒的消息锁定。其思想是从队列的头部弹出一条代理消息,但必须在锁定超时时间内完成.Complete()或.放弃()该消息 如果您不这样做,服务总线将假定您已崩溃或以其他方式失败,并将该消息返回队列以重新处理 您有两个选择: 1) 在处理程序上实现ILongRunningHandler。Nimbus将注意剩余的锁定时间,并自动更新您的消息锁定。警告:无论您续订多少次,ASB/WSB支持的最大消息锁定时间都是5分钟,因此如果处理程序所用时间超过5分钟,则您可能需要选项2
公共类同步器:IHandleCommand、ILongRunningTask
{
公共异步任务句柄(RequestSynchronization synchronizeInfo)
{
Console.WriteLine(“接收到的同步”);
wait Task.Delay(TimeSpan.FromSeconds(30));//模拟长时间运行的进程
WriteLine(“通过第一次超时”);
wait Task.Delay(TimeSpan.FromSeconds(30));//模拟另一个长时间运行的进程
WriteLine(“通过第二次超时”);
}
}
2) 在处理程序中,调用任务。运行(()=>SomeService(yourMessage))并返回。如果您这样做,那么如果您的处理程序接受任何依赖项,请注意依赖项的生命周期范围。如果需要IFoo,请获取对Func>的依赖关系(或取决于容器的等效关系),并在处理任务中解决该问题
public class Synchronizer : IHandleCommand<RequestSynchronization>
{
private readonly Func<Owned<IFoo>> fooFunc;
public Synchronizer(Func<Owned<IFoo>> fooFunc)
{
_fooFunc = fooFunc;
}
public async Task Handle(RequestSynchronization synchronizeInfo)
{
// don't await!
Task.Run(() => {
using (var foo = _fooFunc())
{
Console.WriteLine("Received Synchronization");
await Task.Delay(TimeSpan.FromSeconds(30)); //Simulate long running process
Console.WriteLine("Got through first timeout");
await Task.Delay(TimeSpan.FromSeconds(30)); //Simulate another long running process
Console.WriteLine("Got through second timeout");
}
});
}
}
公共类同步器:IHandleCommand
{
私有只读Func fooFunc;
公共同步器(Func-fooFunc)
{
_fooFunc=fooFunc;
}
公共异步任务句柄(RequestSynchronization synchronizeInfo)
{
//不要等待!
Task.Run(()=>{
使用(var foo=\u fooFunc())
{
Console.WriteLine(“接收到的同步”);
wait Task.Delay(TimeSpan.FromSeconds(30));//模拟长时间运行的进程
WriteLine(“通过第一次超时”);
wait Task.Delay(TimeSpan.FromSeconds(30));//模拟另一个长时间运行的进程
WriteLine(“通过第二次超时”);
}
});
}
}
有趣-默认锁定超时应为1分钟。我不熟悉Nimbus(从他们的网站上看,这需要一点挖掘),但是你是如何从队列中阅读的?您可以在此处增加锁超时,也可以通过BrokeredMessage.RenewLock()
更新锁。
public class Synchronizer : IHandleCommand<RequestSynchronization>
{
private readonly Func<Owned<IFoo>> fooFunc;
public Synchronizer(Func<Owned<IFoo>> fooFunc)
{
_fooFunc = fooFunc;
}
public async Task Handle(RequestSynchronization synchronizeInfo)
{
// don't await!
Task.Run(() => {
using (var foo = _fooFunc())
{
Console.WriteLine("Received Synchronization");
await Task.Delay(TimeSpan.FromSeconds(30)); //Simulate long running process
Console.WriteLine("Got through first timeout");
await Task.Delay(TimeSpan.FromSeconds(30)); //Simulate another long running process
Console.WriteLine("Got through second timeout");
}
});
}
}