@Test public void startReturnDifferentInstances() { ExponentialBackOff backOff = new ExponentialBackOff(); backOff.setInitialInterval(2000L); backOff.setMultiplier(2.0); backOff.setMaxElapsedTime(4000L); BackOffExecution execution = backOff.start(); BackOffExecution execution2 = backOff.start(); assertEquals(2000l, execution.nextBackOff()); assertEquals(2000l, execution2.nextBackOff()); assertEquals(4000l, execution.nextBackOff()); assertEquals(4000l, execution2.nextBackOff()); assertEquals(BackOffExecution.STOP, execution.nextBackOff()); assertEquals(BackOffExecution.STOP, execution2.nextBackOff()); }
@Test public void defaultInstance() { ExponentialBackOff backOff = new ExponentialBackOff(); BackOffExecution execution = backOff.start(); assertEquals(2000l, execution.nextBackOff()); assertEquals(3000l, execution.nextBackOff()); assertEquals(4500l, execution.nextBackOff()); }
@Test public void simpleIncrease() { ExponentialBackOff backOff = new ExponentialBackOff(100L, 2.0); BackOffExecution execution = backOff.start(); assertEquals(100l, execution.nextBackOff()); assertEquals(200l, execution.nextBackOff()); assertEquals(400l, execution.nextBackOff()); assertEquals(800l, execution.nextBackOff()); }
@Test public void fixedIncrease() { ExponentialBackOff backOff = new ExponentialBackOff(100L, 1.0); backOff.setMaxElapsedTime(300l); BackOffExecution execution = backOff.start(); assertEquals(100l, execution.nextBackOff()); assertEquals(100l, execution.nextBackOff()); assertEquals(100l, execution.nextBackOff()); assertEquals(BackOffExecution.STOP, execution.nextBackOff()); }
@Test public void maxIntervalReached() { ExponentialBackOff backOff = new ExponentialBackOff(2000L, 2.0); backOff.setMaxInterval(4000L); BackOffExecution execution = backOff.start(); assertEquals(2000l, execution.nextBackOff()); assertEquals(4000l, execution.nextBackOff()); assertEquals(4000l, execution.nextBackOff()); // max reached assertEquals(4000l, execution.nextBackOff()); }
@Test public void maxAttemptsReached() { ExponentialBackOff backOff = new ExponentialBackOff(2000L, 2.0); backOff.setMaxElapsedTime(4000L); BackOffExecution execution = backOff.start(); assertEquals(2000l, execution.nextBackOff()); assertEquals(4000l, execution.nextBackOff()); assertEquals(BackOffExecution.STOP, execution.nextBackOff()); // > 4 sec wait in total }
@Test public void invalidInterval() { ExponentialBackOff backOff = new ExponentialBackOff(); thrown.expect(IllegalArgumentException.class); backOff.setMultiplier(0.9); }
@Test public void maxIntervalReachedImmediately() { ExponentialBackOff backOff = new ExponentialBackOff(1000L, 2.0); backOff.setMaxInterval(50L); BackOffExecution execution = backOff.start(); assertEquals(50L, execution.nextBackOff()); assertEquals(50L, execution.nextBackOff()); }
@Test public void toStringContent() { ExponentialBackOff backOff = new ExponentialBackOff(2000L, 2.0); BackOffExecution execution = backOff.start(); assertEquals("ExponentialBackOff{currentInterval=n/a, multiplier=2.0}", execution.toString()); execution.nextBackOff(); assertEquals("ExponentialBackOff{currentInterval=2000ms, multiplier=2.0}", execution.toString()); execution.nextBackOff(); assertEquals("ExponentialBackOff{currentInterval=4000ms, multiplier=2.0}", execution.toString()); }
@Override public Response intercept(Chain chain) throws IOException { ExponentialBackOff backoff = new ExponentialBackOff(); backoff.setMaxElapsedTime(maxElapsedBackoffMs); BackOffExecution backOffExec = backoff.start(); Response response = null; long waitTime = 0; while (waitTime != BackOffExecution.STOP) { Request request = chain.request(); response = chain.proceed(request); if (response.isSuccessful() || NON_RETRYABLE_METHODS.contains(request.method()) || response.code() == 404) { return response; } try { waitTime = backOffExec.nextBackOff(); if (waitTime != BackOffExecution.STOP) { response.body().close(); log.warn("Request for " + request.urlString() + " failed. Backing off for " + waitTime + "ms"); Thread.sleep(waitTime); } } catch (Throwable ignored) { break; } } return response; }
public static void handleRegisterClientException(HystrixRuntimeException e, BackOff exponentialBackOff, BackOffExecution backOffExecution, String configServiceUrl) { Throwable cause = e.getCause(); log.debug("Exception registering client, exception getMessage={}", e.getMessage()); log.debug("Exception registering client, cause getMessage={}", cause.getMessage()); if (cause instanceof ConnectException) { log.debug("Connection refused to ConfigService url={}", configServiceUrl); } else if (cause instanceof InternalServerErrorException) { log.debug("Internal server error in ConfigService url={}", configServiceUrl); } else if(cause instanceof NotFoundException) { log.debug("404 not found to ConfigService url={}", configServiceUrl); } else if (cause instanceof BadRequestException) { log.error("400 Bad Request. Probably need to fix something on the client. Exiting after a" + " wait, so as to not DDoS the server."); // TODO Do a sensible BackOff implementation class comparissmnet before this!!! SleepUtil.sleepWithLogging(((ExponentialBackOff)exponentialBackOff).getMaxInterval() * 2); System.exit(1); } else if (cause instanceof TimeoutException) { log.debug("CommandRegisterClient timed out."); } else { log.error("Couldn't handle exception: {}", e); } SleepUtil.sleepWithLogging(backOffExecution.nextBackOff()); }
public ClientConfig registerClient() { BackOff exponentialBackOff = new ExponentialBackOff(); BackOffExecution backOffExecution = exponentialBackOff.start(); while (true) { try { return new CommandRegisterClient(artifactId, configServiceClient, clientName, clientId).execute(); } catch (HystrixRuntimeException e) { RegisterClientExceptionHandler.handleRegisterClientException(e, exponentialBackOff, backOffExecution, configServiceClient.getUrl()); } } }
public static void main(String[] args) { ExponentialBackOff backOff = new ExponentialBackOff(100, 1.5);// 初始间隔,递增倍数(上次基础上) backOff.setMaxInterval(5 * 1000L);// 最大间隔(上一次和下一次最大间隔) backOff.setMaxElapsedTime(50 * 1000L);// 最大总时间间隔(第一次和最后一次间隔) BackOffExecution execution = backOff.start(); for (int i = 1; i <= 18; i++) { System.out.println(execution.nextBackOff()); } System.out.println(execution.nextBackOff()); }