Today’s sharing begins, please give us more advice ~

External services are generally unreliable for callers, especially in the case of poor network environment, and network jitter is easy to lead to abnormal situations such as request timeout. At this time, it is necessary to use the failed retry policy to call the API interface again to get them. The retry policy is also widely used in service governance to see if a service is alive or not through periodic detection.

Spring exception retries the framework Spring Retry

Spring Retry supports integration into Spring or Spring Boot projects, and it supports AOP’s facet injection writing, so the AspectJWeaver.jar package must be included when it is introduced.

1. Introduce Maven dependencies

2. Add @Retyable and @Recover annotations

The @Retryable annotation retries the annotated method when an exception occurs

  • Value: Specifies the exception that occurred to retry
  • Include: includes: is null by default, and all exceptions are retried when exclude is also null
  • Exclude: specifies that the exception will not be retried, default is null, and all exceptions will be retried if include is also null
  • MaxAttemps: Number of retries, default 3
  • Backoff: Retry compensation mechanism, none by default

@ Backoff annotations

  • Delay: Retry after specifying a delay
  • Multiplier: Specifies a multiple of the delay, such as delay= 5000L,multiplier=2, the first retry is 5 seconds, the second retry is 10 seconds, and the third retry is 20 seconds

Recover annotation: When the retry reaches the specified number, the annotated method will be called back and log processing can be done in that method. Note that the callback only occurs when the exception occurs and the input parameter type is the same.

3. Enable retry

Add the @Enableretry annotation to the startup class, EnableRetry, or add it to the Service that uses Retry, or to the Configuration class. It is recommended that all Enable configurations be added to the boot class so that the functions used can be clearly managed.

4. Start the service and run the tests

Guava based retry component guava-retryer

Read the component author’s description of this component directly:

This is a small extension to Google’s Guava Library to allow for the creation of configurable retrying strategies for an information system arbitrary function call, This is a small extension to Google’s Guava library that allows you to create a configurable retry policy for any function call. For example, the policy of talking to remote services with erratic runtimes.

The first step is to introduce Maven coordinates:

1. Introduction of main interfaces and strategies

  • Attempt: a mission;
  • Attempttimelimiter: Single task execution time limit (terminates current task if a single task execution time out);
  • BlockStrategies: Task BlockStrategies (in layman’s terms, what to do in the period between the completion of the current task and the start of the next task… Thread.sleep(sleepTime); Thread.sleep(sleepTime);
  • RetryException: retry the exception;
  • RetryListener: A custom RetryListener that can be used to asynchronously log errors.
  • StopStrategy: The stop-retry strategy is available in three ways:
  • StopAfterDelayStrategy: Sets the maximum allowable execution time; For example, if the maximum execution time is set to 10s, no matter how many times the task is executed, as long as the retry exceeds the maximum time, the task is terminated and the RetryException RetryException is returned.
  • NeverStopStrategy: Do not stop, used in cases where you need to keep rotating until the desired result is returned;
  • AttemptStrategy: Sets the maximum number of retries, if exceeded, to stop retries and return a retry exception;
  • WaitStrategy, which returns the next execution time:
  • FixedWaitStrategy: Fixed wait time strategy;
  • RandomWaitStrategy: Random wait time strategy (can provide a minimum and maximum wait time, with the wait time being its interval random value)
  • IncrementingWaitStrategy: Incremental wait time policy (provides an initial value and step size, and the wait time increases with retries)
  • ExponentialWaitStrategy: Exponential wait time strategy;
  • FibonacciWaitStrategy: Fibonacci wait time policy;
  • ExceptionWaitStrategy: ExceptionWaitStrategy
  • CompositeWaitStrategy: a composite time-waiting strategy

2. Determine whether to retry based on the results

Use scenario: If the return value determines whether to retry. Retry interface:

Testing:

Output:

3. Determine whether to retry according to the exception

Use scenario: Whether to perform a retry based on the type of exception thrown. Retry interface:

Testing:

Output:

4. Retry Policy — Set unlimited retries

Usage scenario: in the case of an exception, unlimited retry (default execution policy) until the return of normal valid results;

5. Retry Policy — Set the maximum number of retries

Usage scenario: in the case of an exception, the maximum number of retries, if more than the number will throw an exception;

Testing:

Output:

6. Wait Policy — Set a retry wait policy for a fixed amount of time

Usage scenario: set the waiting interval for each retry to be fixed at 10s;

To test the output, we can see that the call interval is 10S:

7. Waiting strategy — Set a fixed increase in the wait time for retries

Scenario: Set the initial waiting time value, and set the fixed increase step size, but do not set the maximum waiting time;

To test the output, we can see that the call interval is incremented by 1 second:

8. Waiting strategy — Set up an exponential growth strategy for the wait time for retries

Usage scenario: Increase the waiting time exponentially according to the value of Multiplier, and set the maximum waiting time;

The retry policy and input parameters are not very clear, ok, check the source code:

From the source code to see ExponentialWaitStrategy is an immutable internal class, the constructor validates the parameter, the most important delay time calculation method computeLeepTime (), you can see the delay time calculation method

Calculate the number of failures exponential to base 2

The value constructor of the first step multiplies the first argument and then rounds it to get the delay time (milliseconds)

According to the above analysis, the time interval should be 2,4,8 s when the input parameter is 1000

2×1000, 4×1000, 8×1000:

9. Waiting strategy — Set the waiting time for retry according to the Fibonacci sequence strategy

Usage scenario: Increase the waiting time according to the value of Multiplier and set the maximum waiting time, Fibonacci sequence: 1, 1, 2, 3, 5, 8, 13, 21, 34…

Again, if you look at the source code and you calculate that the delay time is the product of the Fibonacci sequence and the first input parameter in milliseconds

1×1000, 1×1000, 2×1000:

10. Wait strategy — Combine the retry wait length strategy

Usage scenarios: When an existing policy does not meet a usage scenario, multiple policies can be used in combination.

Again, look at the source code to understand what composite policy means:

It can be seen that the delay time of the combined strategy is actually obtained by summing the delay time of multiple strategies. ExponentialWait has latency of 2,4,8,16,32… , FixedWait delay is 2, 2, 2, 2… , so the total delay time is 4,6,10,18,34…

Test output:

11. Listener — RetryListener implementation retry process details handling

Usage Scenarios: Custom listeners that print the details of the retry process separately, and may be used more in the future for asynchronous logging or special processing.

Testing:

Output:

conclusion

Both methods are elegant retry strategies. Spring-Retry is easier to configure and has relatively simple functions. Guava itself is a superb Java class library released by Google. Compared with spring-retry, spring-retry is more selective in whether to Retry or not, and can be used as a supplement to spring-retry.