【问题标题】:How should I handle backoff or "Wait and Retry" logic in a C# application when an exception occurs?发生异常时,我应该如何处理 C# 应用程序中的退避或“等待并重试”逻辑?
【发布时间】:2013-10-15 22:34:52
【问题描述】:

我正在从 REST 服务读取数据,需要处理“等待并重试”的频繁使用服务,这会给我一个错误:

每秒查询太多

服务器忙

一般来说,由于我有许多 REST 服务要调用,我一般如何处理发生异常时会发生的退避逻辑?

有没有内置的框架?我只是想编写干净的代码,而不必过多担心管道和基础架构。

【问题讨论】:

  • 查看供应商提供的文档或联系支持人员,询问他们有哪些限制。如果您使用的是谷歌地图 API,它大约是每秒 1 次。

标签: c# web-services rest exception webclient


【解决方案1】:

您可以将尝试包装在为您处理重试逻辑的方法中。例如,如果您使用WebClient 的异步方法:

public async Task<T> RetryQuery<T>(Func<Task<T>> operation, int numberOfAttempts, int msecsBetweenRetries = 500)
{
     while (numberOfAttempts > 0)
     {
          try
          {
               T value = await operation();
               return value;
          }
          catch
          {
                // Failed case - retry
                --numberOfAttempts;                   
          }

          await Task.Delay(msecsBetweenRetries);
     }

     throw new ApplicationException("Operation failed repeatedly");
}

然后您可以通过以下方式使用它:

// Try 3 times with 500 ms wait times in between
string result = await RetryQuery(async () => webClient.DownloadStringTaskAsync(url), 3);

【讨论】:

  • +1,但是里德,微软建议不要再使用ApplicationException。我会改用ExceptionInvalidOperationException
【解决方案2】:

尝试确定一次可以激活多少活动请求并使用Semaphore

这是一种处理资源锁定的方法,其中有多个相同的资源,但数量有限。

Here's the MSDN documentation on semaphores

【讨论】:

  • 我没有投反对票,但我没有使用多线程,只是一个串行控制台实现。如果我是,信号量会很棒/很有必要。不确定我是否需要使用 TPL 库
【解决方案3】:

我建议您查看 Transient Fault Handling Application Block,它是企业库的一部分。

过去,IMO 对 EL 进行了过度设计,没有那么有用,但他们已采取措施解决这个问题; TFHAB 是遵循更好的设计指南(同样是 IMO)的较新模块之一。

【讨论】:

    猜你喜欢
    • 2017-03-03
    • 2013-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多