NServiceBus6延迟恢复而不是延迟

时间:2018-06-01 19:57:43

标签: nservicebus nservicebus6

如果没有非常详细地讨论我们试图解决的问题,我需要让NServiceBus做5件事之一,但我目前只是想让第一件工作。也就是说,如果从Web API调用回复,我们希望延迟重试,立即重试,放弃,取消或重新开始。延迟重试看起来最好使用自定义可恢复性,所以我按照这个:Custom Recoverability Policy并提出了这个

public static class UpdateEndpointConfiguration
{
    public static void ConfigureEndpointForUpdateVocxoSurveyApi(this EndpointConfiguration configuration)
    {
        var recoverabilitySettings = configuration.Recoverability();
        recoverabilitySettings.CustomPolicy(SetCustomPolicy);
    }

    private static RecoverabilityAction SetCustomPolicy(RecoverabilityConfig config, ErrorContext context)
    {
        var action = DefaultRecoverabilityPolicy.Invoke(config, context);
        if (context.Exception is DelayedRetryException delayedRetryException)
        {
            return RecoverabilityAction.DelayedRetry(TimeSpan.FromSeconds(delayedRetryException.DelayRetryTimeoutSeconds));
        }
        return action;
    }
}

然后作为一个测试,我做了一个简单的消息,所以我不必强迫web api做傻事:

public class ForceDelayRetry : ICommand
{
    public int DelayInSeconds { get; set; }
}

然后“处理它”

public class TestRequestHandler : IHandleMessages<ForceDelayRetry>
{
    private static readonly ILog Log = LogManager.GetLogger(typeof(TestRequestHandler));

    public async Task Handle(ForceDelayRetry message, IMessageHandlerContext context)
    {
        Log.Info($"Start processing {nameof(ForceDelayRetry)}");
        var handleUpdateRequestFailure = IoC.Get<HandleUpdateRequestFailure>();
        await handleUpdateRequestFailure.HandleFailedRequest(new UpdateRequestFailed
        {
            DelayRetryTimeoutSeconds = message.DelayInSeconds,
            Message = $"For testing purposes I am forcing a delayed retry of {message.DelayInSeconds} second(s)",
            RecoveryAction = RecoveryAction.DelayRetry
        }, context, 12345);
        Log.Info($"Finished processing {nameof(ForceDelayRetry)}");
    }
}

我启动服务,在大约1.5分钟的时间内,两条测试消息大约处理了5,400次。日志消息看起来与此类似(为简洁起见,省略了堆栈跟踪)

20180601 15:28:47 :INFO  [14] TestRequestHandler Start processing ForceDelayRetry
20180601 15:28:47 :WARN  [22] NServiceBus.RecoverabilityExecutor Delayed Retry will reschedule message '690f317e-5be0-4511-88b9-a8f2013ac219' after a delay of 00:00:01 because of an exception:
20180601 15:28:47 :INFO  [14] TestRequestHandler Start processing ForceDelayRetry
20180601 15:28:47 :WARN  [14] NServiceBus.RecoverabilityExecutor Delayed Retry will reschedule message '7443e553-b558-486d-b7e9-a8f2014088d5' after a delay of 00:00:01 because of an exception:
20180601 15:28:47 :INFO  [4] TestRequestHandler Start processing ForceDelayRetry
20180601 15:28:47 :WARN  [14] NServiceBus.RecoverabilityExecutor Delayed Retry will reschedule message '690f317e-5be0-4511-88b9-a8f2013ac219' after a delay of 00:00:01 because of an exception:
20180601 15:28:47 :INFO  [14] TestRequestHandler Start processing ForceDelayRetry
20180601 15:28:47 :WARN  [14] NServiceBus.RecoverabilityExecutor Delayed Retry will reschedule message '7443e553-b558-486d-b7e9-a8f2014088d5' after a delay of 00:00:01 because of an exception:

所以要么我做错了,要么有错误,但我不知道哪个。任何人都可以看到问题所在吗?

修改

这是方法handleUpdateRequestFailure.HandleFailedRequest

    public async Task HandleFailedRequest(UpdateRequestFailed failure, IMessageHandlerContext context, long messageSurveyId)
    {
        switch (failure.RecoveryAction)
        {
            case RecoveryAction.DelayRetry:
                Log.InfoFormat("Recovery action is {0} because {1}. Retrying in {2} seconds", failure.RecoveryAction, failure.Message, failure.DelayRetryTimeoutSeconds);
                await context.Send(_auditLogEntryCreator.Create(_logger.MessageIsBeingDelayRetried, messageSurveyId));
                throw new DelayedRetryException(failure.DelayRetryTimeoutSeconds);
            case RecoveryAction.EndPipelineRequest:
            case RecoveryAction.RestartPipelineRequest:
            case RecoveryAction.RetryImmediate:
            case RecoveryAction.RouteToErrorQueue:
                break;
        }
    }

并且正如评论所指出的那样,我会对我的消息进行无限重试,我也发现了这一消息,但这里有更新的逻辑

    private static RecoverabilityAction SetCustomPolicy(RecoverabilityConfig config, ErrorContext context)
    {
        var action = DefaultRecoverabilityPolicy.Invoke(config, context);
        if (context.Exception is DelayedRetryException delayedRetryException)
        {
            if (config.Delayed.MaxNumberOfRetries > context.DelayedDeliveriesPerformed)
                return RecoverabilityAction.DelayedRetry(TimeSpan.FromSeconds(delayedRetryException.DelayRetryTimeoutSeconds));
        }
        return action;
    }

1 个答案:

答案 0 :(得分:0)

  

这是因为给定了来自Web API调用的回复,我们希望延迟重试,立即重试,放弃,取消或重新开始。延迟重试看起来最好使用自定义可恢复性

除了NServiceBus已经提供的内容之外,我不确定我理解你要实现的目标是什么?让立即和延迟重试做最好的事情:做实际的重试。

如果您想要更多功能,请使用传奇。让saga编排流程并让一个单独的处理程序对外部服务进行实际调用。然后,根据此处理程序的回复,该传奇可以决定是否应该停止,继续,采取替代路径等。

如果您想进一步讨论这个问题,我建议您通过support@particular.net与我们联系,我们可以召开电话会议,向您展示我们如何做到这一点。