没有详细说明我们试图解决的问题,我需要让NServiceBus做5件事情中的1件,但我目前只是想让第一件事情开始工作。也就是说,如果从web调用返回一个回复,我们希望有一个延迟的重试,立即重试,放弃,取消或重新开始。延迟重试看起来最好使用自定义的可恢复性,所以我遵循了以下步骤:自定义可恢复策略并提出了以下建议
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做一些愚蠢的事情了:
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分钟的时间内,这两条测试消息被处理了大约5400次。日志消息看起来与此类似(为了简洁起见,省略了堆栈跟踪)
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方法
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;
}发布于 2018-06-05 09:08:46
也就是说,如果从web调用返回一个回复,我们希望有一个延迟的重试,立即重试,放弃,取消或重新开始。延迟重试看起来最好使用自定义可恢复性。
除了NServiceBus已经提供的内容之外,我不确定我是否理解您正在尝试实现什么?让立即和延迟的重试做它是最好的:做实际的重试。
如果你想要更多的功能,可以使用传奇。让saga编排流程,并让一个单独的处理程序执行对外部服务的实际调用。然后,根据这个处理程序的答复,佐贺可以决定它是否应该停止、继续、选择另一条路径等等。
如果您想进一步讨论这个问题,我建议您在support@particular.net与我们联系,我们可以安排一个电话会议,并向您展示我们将如何做到这一点。
https://stackoverflow.com/questions/50650267
复制相似问题