如果没有非常详细地讨论我们试图解决的问题,我需要让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;
}
答案 0 :(得分:0)
这是因为给定了来自Web API调用的回复,我们希望延迟重试,立即重试,放弃,取消或重新开始。延迟重试看起来最好使用自定义可恢复性
除了NServiceBus已经提供的内容之外,我不确定我理解你要实现的目标是什么?让立即和延迟重试做最好的事情:做实际的重试。
如果您想要更多功能,请使用传奇。让saga编排流程并让一个单独的处理程序对外部服务进行实际调用。然后,根据此处理程序的回复,该传奇可以决定是否应该停止,继续,采取替代路径等。
如果您想进一步讨论这个问题,我建议您通过support@particular.net与我们联系,我们可以召开电话会议,向您展示我们如何做到这一点。