Retry or Not Retry

2019-03-02 23:43|来源: 网路

[注:此为译文,原文 trace back: https://ljfang.wordpress.com/2011/05/21/to-retry-or-not-to-retry/]

在大型分布式系统中,retry 是一个很重要的应对 transient failure 的 workaround。在分布式系统中,failure 会频繁的发生。我们需要适应这些变化保证总体的 reliability 和 availability。例如, Service A 发送一个 request 给 Service B。 它可能超时,因为网络问题,或者因为 Service B 太忙了。所以 Service A 会重发 request 给 B 并且希望这次它可以得到 B 的成功响应,那么问题来了,A 应该继续重发 request 直到它成功收到 B 的响应么?

除了 transient error,还有一些别的原因可以导致请求失败。比如,request 是非法的,B 无法处理非法的 request。在这种情况下,通常 A 会收到 B 的一个显式的 error code 以表明 request 的非法性。另一个原因也可以是,B 的 bug,A 的 request 触发了 B 的 bug。在处理特定的 request 时,B 可能会 crash,deadlock,或者 hang,有 CPU Spike,或者处理 request 时非常耗时。当这其中任何一个是 root cause 时,A 重发请求反而会继续触发该 bug 并导致 B 对别的 request、别的 user、别的 service 的不可用。这就演变成了 DOS 攻击。在这种情况下,很显然 A 不应该给 B 重发请求。

在某些不确定的场合下 retry 有时也会引入额外的网络负载。如果每个人都去 retry,这就很可能导致某种 request storm (e.g. the re-mirroring storm in Amazon),最终导致网络瘫痪。

通常意义上,retry 在分布式系统中时一个处理 transient error 的好办法。但是,retry 不应该用在不确定的场合。

(1) 不要过度使用 retry。我们应该从一次 retry 到下一次 retry 降低 retry 的频率。例如,第一次 retry 的发出可以是初始 request 发出之后的 5s;第二次 retry 的发出可以是第一次 retry 后的 20s;精确的时间周期取决于系统和 request 类型。例如,初始的周期可以是 100ms,1s,5m …

(2) 限制 retry 次数。Again,retry 总数其实取决于特定的系统。它可以是 3,5,10,etc。但是它一定是有上限的。不要没完没了的 retry。如果达到次数上限时 request 仍然失败,系统肯定是有地方出了问题。这样的 event 应当被 log 下来,开发团队应当被 alert,这样他们就可以展开调查并最终解决问题。

<EOF>


转自:http://www.cnblogs.com/rmcary/archive/2012/12/02/2798486

相关问答

更多
  • 您可以使用retryWhen()运算符将重试逻辑添加到任何Observable。 以下类包含重试逻辑: RxJava 2.x public class RetryWithDelay implements Function, Observable> { private final int maxRetries; private final int retryDelayMillis; private int retry ...
  • Spring Kafka附带了RetryingMessageListenerAdapter和RetryingAcknowledgingMessageListenerAdapter 。 如果使用@KafkaListener ,则可以使用@KafkaListener提供AbstractKafkaListenerContainerFactory 。 最后一个可以使用Spring Retry项目中的任何自定义RetryPolicy和BackOffPolicy注入: https://docs.spring.io/sp ...
  • Angular的基础 - HttpClient - retry()声明: RxJS库提供了一些值得探索的重试操作符。 最简单的称为retry(),它会自动重新订阅失败的Observable指定的次数。 重新订阅HttpClient方法调用的结果具有重新发送HTTP请求的效果。 所以每次你调用flush都会抛出一个打开的请求。 您只需重复请求处理并在服务重试请求的同时多次刷新。 it('can test for 404 error', () => { const emsg = 'deliberate 4 ...
  • 你不能严格地“重试”一个AsyncTask的实例。 您必须创建一个新实例并执行它,就像您完成第一个实例一样。 你不应该遇到递归问题。 You cannot strictly "retry" an instance of AsyncTask. You have to create a new instance and execute it, just as you did the first one. You should not encounter a recursion problem.
  • 如果出现错误,它将执行5次,但事实并非如此。 尝试这个 i = 0 begin p "5 times" raise "error" rescue i += 1 retry if i < 5 end 如果您希望在没有例外的情况下执行代码,请使用ensure ,但不能从那里retry 。 i = 0 begin p "5 times" rescue # won't run if there are no exceptions i += 1 retry if i < 5 ensu ...
  • Spring Retry不是你想要的。 这就是幂等操作,你只需再试一次。 这是OAuth令牌吗? 然后你想要Spring Security OAuth 。 即使不是你想做Oauth2RestTemplate所做的事情:将令牌处理挂钩到客户端。 Spring Retry is not what you want. That is for idempotent operations where you literally just try again. Is this an OAuth token? Then ...
  • 您可以使用np.errstate上下文管理器来捕获警告,就好像它是一个异常: while True: try: print("Before mcmc") with np.errstate(all='raise'): sampler.run_mcmc(pos, 500) print("After mcmc") break except Exception: print("Warning de ...
  • retry在rescue块(或迭代器)中工作。 它适用于if 。 尝试这个: begin bet = Dialogs.enter_your_bet approx.calculate_average_profit(bet) approx.print_profits_table rescue retry if Dialogs.play_again? end Ok, thank you all for answers! I understood what was a problem, but y ...
  • 如何创建以下界面: public interface IRetryCondition { TResult Until(Func condition); } public class RetryCondition : IRetryCondition { private TResult _value; private Func> _retry; ...
  • Stormpath API尚未提供此功能,因此必须由Web应用程序管理。 但是,Stormpath API可以帮助您,因为您可以将状态存储在帐户的自定义数据对象中,以便您可以跟踪对该特定帐户的尝试次数。 我希望这个答案有所帮助! The Stormpath API does not yet provide this as a feature, so this is something that would have to be managed by your web application. However ...