首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >NServiceBus6延迟恢复不延迟

NServiceBus6延迟恢复不延迟
EN

Stack Overflow用户
提问于 2018-06-01 19:57:43
回答 1查看 147关注 0票数 0

没有详细说明我们试图解决的问题,我需要让NServiceBus做5件事情中的1件,但我目前只是想让第一件事情开始工作。也就是说,如果从web调用返回一个回复,我们希望有一个延迟的重试,立即重试,放弃,取消或重新开始。延迟重试看起来最好使用自定义的可恢复性,所以我遵循了以下步骤:自定义可恢复策略并提出了以下建议

代码语言:javascript
运行
复制
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做一些愚蠢的事情了:

代码语言:javascript
运行
复制
public class ForceDelayRetry : ICommand
{
    public int DelayInSeconds { get; set; }
}

然后“处理”

代码语言:javascript
运行
复制
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分钟的时间内,这两条测试消息被处理了大约5400次。日志消息看起来与此类似(为了简洁起见,省略了堆栈跟踪)

代码语言:javascript
运行
复制
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:

所以要么我做错了什么,要么有个bug,但我不知道是哪一个。有人能看到问题所在吗?

编辑

下面是handleUpdateRequestFailure.HandleFailedRequest方法

代码语言:javascript
运行
复制
    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;
        }
    }

正如评论指出的那样,我也会对我的消息进行无限重试,但这是更新的逻辑。

代码语言:javascript
运行
复制
    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;
    }
EN

回答 1

Stack Overflow用户

发布于 2018-06-05 09:08:46

也就是说,如果从web调用返回一个回复,我们希望有一个延迟的重试,立即重试,放弃,取消或重新开始。延迟重试看起来最好使用自定义可恢复性。

除了NServiceBus已经提供的内容之外,我不确定我是否理解您正在尝试实现什么?让立即和延迟的重试做它是最好的:做实际的重试。

如果你想要更多的功能,可以使用传奇。让saga编排流程,并让一个单独的处理程序执行对外部服务的实际调用。然后,根据这个处理程序的答复,佐贺可以决定它是否应该停止、继续、选择另一条路径等等。

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50650267

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档