如果其中一个服务由于某种原因而出错,那么编排传奇应该如何表现呢?

时间:2018-05-14 10:54:11

标签: nservicebus

我一直试图解决这个问题一段时间,但是我无法理解它。

当请求服务-A(也使用具有主要和延迟重试的nservicebus实现),并且服务A由于瞬态/半瞬态错误而失败时,服务将重试,直到所有重试都用完为止消息被发送到错误队列(假设我们正在使用ASB或rabbitmq或者msmq),在服务A的响应决定传奇是否发出请求服务B或C的情况下,传奇应该如何表现。 或者如果saga在设定的时间内没有收到预期的响应,那么它应该超时,然后通过对在service-A之前执行的任何其他服务(如果需要补偿)进行补偿请求来进行...或者我应该实现自定义错误在每个服务中处理以处理瞬态/半瞬态错误并让传奇知道是否发生了故障(如果这是解决问题的方法......我可以使用默认的nservicebus重试).....请建议......

1 个答案:

答案 0 :(得分:1)

来自服务的回复将是最后一步,这意味着所有其他步骤(可能导致失败)已经过去。如果/一旦编排saga收到回复消息,它就知道服务已经完成了它的工作。

在传奇中你有:

public class MySaga : IAmStartedBy<SagaStart>, IHandleMessage<OperationPerformed>
{
    //You'll need to map/store some sort of a ID to know the replies
    //that come back are related to which saga instance

    public Task Handle(SagaStart startMessage, IMessageContext context) 
    {
        await context.Send(new PerformOperation() 
        {
           OperationId = startMessage.Id
        });
    }

    public Task Handle(OperationPerformed message, IMessageContext context) 
    {
        //Operation has succeeded.
        //Maybe saga is finished at this point?
        MarkAsComplete();
        return Task.CompletedTask;
    }
}

public class OperationService : IHandleMessages<PerformOperation>
{
    public async Task Handle(OperationPerformed message, IMessageContext context)
    {
        //call external service
        await httpClient.PerformNetworkBoundCall(); // <- Could fail

        await context.Reply(new OperationPerformed()
        {
            OperationId = message.OperationId
        });
    }
}

现在,当您拥有的服务不仅仅是一项服务并且需要等待所有服务完成以执行下一步(或完成)时,事情可能会变得更有趣。请记住,消息或回复可能会失灵,这正是Sagas闪耀的地方。