问题描述
我正在编写一些重新连接逻辑,以定期尝试建立与远程端点的连接.本质上,代码看起来像这样:
public void establishConnection() { try { this.connection = newConnection(); } catch (IOException e) { // connection failed, try again. try { Thread.sleep(1000); } catch (InterruptedException e) {}; establishConnection(); } }
我已经在许多情况下解决了与上述代码相似的代码的一般问题,但是我对结果不满意.是否有用于处理此问题的设计模式?
推荐答案
无耻的插头:我已经实施了一些类以重试操作. 库尚未提供,但是您可以https://github.com/ninja-squad/ninja-core/tree/tree/master/master/src/main/main/java/java/java/ninja_squad/core/core/core/core/core/core/core/重试github上的叉子 .
和 fork 存在.
它允许构建具有各种灵活策略的重试器.例如:
Retryer retryer = RetryerBuilder.newBuilder() .withWaitStrategy(WaitStrategies.fixedWait(1, TimeUnit.SECOND)) .withStopStrategy(StopStrategies.stopAfterAttempt(3)) .retryIfExceptionOfType(IOException.class) .build();
然后,您可以使用重试者执行可呼叫(或几个):
retryer.call(new Callable<Void>() { public Void call() throws IOException { connection = newConnection(); return null; } }
其他推荐答案
您可以尝试 idempotent retry taters .
.
其他推荐答案
我真的很喜欢此Java 8代码,来自此博客,您不需要classpath上的任何额外库.
您只需要将功能传递给重试类.
@Slf4j public class RetryCommand<T> { private int maxRetries; RetryCommand(int maxRetries) { this.maxRetries = maxRetries; } // Takes a function and executes it, if fails, passes the function to the retry command public T run(Supplier<T> function) { try { return function.get(); } catch (Exception e) { log.error("FAILED - Command failed, will be retried " + maxRetries + " times."); return retry(function); } } private T retry(Supplier<T> function) throws RuntimeException { int retryCounter = 0; while (retryCounter < maxRetries) { try { return function.get(); } catch (Exception ex) { retryCounter++; log.error("FAILED - Command failed on retry " + retryCounter + " of " + maxRetries, ex); if (retryCounter >= maxRetries) { log.error("Max retries exceeded."); break; } } } throw new RuntimeException("Command failed on all of " + maxRetries + " retries"); } }
并使用它:
new RetryCommand<>(5).run(() -> client.getThatThing(id));
问题描述
I'm writing some reconnect logic to periodically attempt to establish a connection to a remote endpoint which went down. Essentially, the code looks like this:
public void establishConnection() { try { this.connection = newConnection(); } catch (IOException e) { // connection failed, try again. try { Thread.sleep(1000); } catch (InterruptedException e) {}; establishConnection(); } }
I've solved this general problem with code similar to the above on many occasions, but I feel largely unsatisfied with the result. Is there a design pattern designed for dealing with this issue?
推荐答案
Shameless plug: I have implemented some classes to allow retrying operations. The library is not made available yet, but you may fork it on github.
And a fork exists.
It allows building a Retryer with various flexible strategies. For example:
Retryer retryer = RetryerBuilder.newBuilder() .withWaitStrategy(WaitStrategies.fixedWait(1, TimeUnit.SECOND)) .withStopStrategy(StopStrategies.stopAfterAttempt(3)) .retryIfExceptionOfType(IOException.class) .build();
And you can then execute a callable (or several ones) with the Retryer:
retryer.call(new Callable<Void>() { public Void call() throws IOException { connection = newConnection(); return null; } }
其他推荐答案
You could try the Idempotent Retry Pattern.
其他推荐答案
I really like this Java 8 code from this blog and you don't need any extra library on your classpath.
You only need to pass a function to the retry class.
@Slf4j public class RetryCommand<T> { private int maxRetries; RetryCommand(int maxRetries) { this.maxRetries = maxRetries; } // Takes a function and executes it, if fails, passes the function to the retry command public T run(Supplier<T> function) { try { return function.get(); } catch (Exception e) { log.error("FAILED - Command failed, will be retried " + maxRetries + " times."); return retry(function); } } private T retry(Supplier<T> function) throws RuntimeException { int retryCounter = 0; while (retryCounter < maxRetries) { try { return function.get(); } catch (Exception ex) { retryCounter++; log.error("FAILED - Command failed on retry " + retryCounter + " of " + maxRetries, ex); if (retryCounter >= maxRetries) { log.error("Max retries exceeded."); break; } } } throw new RuntimeException("Command failed on all of " + maxRetries + " retries"); } }
And to use it:
new RetryCommand<>(5).run(() -> client.getThatThing(id));