This is the 19th day of my participation in the Gwen Challenge in November. Check out the details: The last Gwen Challenge in 2021

The service background of the retry mechanism

External services are generally unreliable for callers, especially when the network environment is poor. Network jitter can easily lead to request timeout and other exceptions. In this case, the API interface needs to be re-invoked using the retry failure policy to obtain external services.

In a distributed system, to ensure the consistency of distributed data transactions, a retry operation is performed when the network jitter request may time out when the RPC interface is invoked or MQ is sent. MQ is the most popular way to retry, but if MQ is not introduced in your project, it is inconvenient.

Introduction and limitations of retry policies

Retry strategies are also widely used in service governance to check whether a service is alive or not through periodic checks.

Retry is not suitable for all scenarios, such as invalid parameter verification and write operations (whether the write is idempotent or not).

  • Remote call timeout, sudden network interruption can be retried. Microservice governance frameworks usually have their own retry and timeout configurations. For example, dubbo can set retries=1 and timeout=500 to retry only once after a call fails. If the call fails after 500ms, the call fails.

What are the retry scenarios?

If an external RPC call or data entry operation fails, multiple retries can be performed to improve the probability of the call success.

Commonly used retry framework

  • Spring Retry framework: Spring Retry supports integration into Spring or Spring Boot projects, and it supports AOP’s aspect injection writing, so the AspectJweaver. Jar package must be introduced.

  • Sisyphus combines the benefits of Spring-Retry and Gauva-Retrying and is flexible to use.

  • Github.com/houbb/sisyp…

  • The Guava-Retrying module provides a generic way to retry arbitrary Java code using guava predicate matching enhanced specific stop, retry, and exception-handling capabilities.

Spring-retry retry mechanism

Spring Retry provides declarative Retry support for Spring applications. It is used for Spring for Spring batch processing, Spring integration, Apache Hadoop(and so on).

This is a small extension to Google’s Guava Library, which allows you to work with different retrying strategies arbitrary function call, such as something that talks to a remote service with flaky uptime.

Maven configuration

Enabling the Retry Function

Add the @enableretry annotation on the startup class to EnableRetry, or on services that use retry, or on the Configuration class. It is recommended that all Enable configurations be added to the startup class to clearly unify the functions used.

Add the @retryable and @recover annotations

@retryable annotations are retried when an exception occurs over the annotated method
  • Value: specifies the exception to be retried
  • Include: Like value, is null by default. When exclude is also null, all exceptions are retried
  • Exclude: specifies that exceptions are not retried. The default value is null. If include is also empty, all exceptions are retried
  • Maxattem: Number of retries, default is 3
  • Backoff: the retry compensation mechanism is unavailable by default
@ Backoff annotations
  • Delay: Retry after the specified delay

  • Multiplier: Specifies the delay multiplier. For example, if delay= 5000L, Multiplier =2, the first retry is 5 seconds later, the second retry is 10 seconds, and the third retry is 20 seconds

@ Recover annotations

When a specified number of retries are reached, the annotated method is called back and logging can take place in that method. It is important to note that the callback occurs only when the exception is of the same type as the input parameter.

guava-retry

The Guava-Retrying module provides a generic way to retry arbitrary Java code using guava predicate matching enhanced specific stop, retry, and exception-handling capabilities.

Git address of guava-Retry

Github.com/rholder/gua…

advantage

The Guava Retryer tool is similar to Spring-Retry in that it packages logical retries by defining the retries role. However, the Guava Retryer has a better policy definition. In addition to controlling the number of retries and retry frequency, the Guava Retryer tool is compatible with retry source definitions that support multiple exceptions or user-defined entity objects. Give the retry feature more flexibility.

Guava Retryer is thread-safe, entrance to call logic used is Java. The util. Concurrent. The call () method of the Callable exception encountered, retry 3 times to stop

public static void main(String[] args) {
    Callable<Boolean> callable = new Callable<Boolean>() {
        @Override
        public Boolean call(a) throws Exception {
            // do something useful here
            LOGGER.info("call...");
            throw newRuntimeException(); }}; Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder() .retryIfResult(Predicates.isNull()) .retryIfExceptionOfType(IOException.class) .retryIfRuntimeException() .withStopStrategy(StopStrategies.stopAfterAttempt(3))
            .build();
    try {
        retryer.call(callable);
    } catch(RetryException | ExecutionException e) { e.printStackTrace(); }}Copy the code

Its main interface and strategy introduction

  • Attempt to do STH.
  • AttemptTimeLimiter: Time limit for a single task (if a single task times out, the current task is terminated)
  • BlockStrategies: Task blocking strategies (generally speaking, what to do during the period when the current task is executed and the next task is not started… — blockstrategies. THREAD_SLEEP_STRATEGY call thread. sleep(sleepTime);
  • RetryException: RetryException.
  • RetryListener: a custom RetryListener that can be used to log errors asynchronously.
  • StopStrategy: stop retry policy, which can be:
  • StopAfterDelayStrategy: Set a maximum allowed execution time; For example, the maximum retry time is set to 10 seconds. If the retry time exceeds the maximum retry time, the task is terminated and RetryException is returned.
  • NeverStopStrategy: never stopping, used when rotating until the desired result is returned;
  • StopAfterAttemptStrategy: Sets the maximum number of retries. If the maximum number of retries is exceeded, the retries are stopped and a retry exception is returned.
  • WaitStrategy: wait time policy (control time interval), and the result is the next execution time:
  • FixedWaitStrategy: Fixed waiting time strategy;
  • RandomWaitStrategy: random waiting time strategy (can provide a minimum and maximum waiting time, the waiting time is their interval random value)
  • IncrementingWaitStrategy: Incrementing wait time strategy (provide an initial value and step size, wait time increases with retry count)
  • ExponentialWaitStrategy: ExponentialWaitStrategy;
  • FibonacciWaitStrategy: Fibonacci wait duration strategy.
  • ExceptionWaitStrategy: Wait policy for abnormal duration.
  • CompositeWaitStrategy: CompositeWaitStrategy;

Determine whether to retry based on the result

Usage scenario: If the return value determines whether to retry.

Retry interface

Retry policy sets unlimited retry

Usage scenario: In the case of exceptions, infinite retry (default execution policy) until a valid result is returned.

Determine whether to retry based on the exception

Usage scenario: Determine whether to retry based on the type of exceptions thrown.

Wait policy – Sets a fixed retry wait policy

Application scenario: Set the waiting interval for each retry to 10s.

Wait policy – Set a fixed growth policy for retry wait times

Scenario: Set the initial waiting time value and set a fixed growth step, but not set the maximum waiting time;

For example: call interval incremented by 1 second:

Summary of the retry framework

The commonality and principle of elegant retry

  • The normal and retry elegance are decouples, with retry assertion condition instances or logical exception instances being the medium of communication between the two. Another way is for developers to write their own retry mechanisms, but most are not elegant

  • Specify the retry interval, configure different retry policies, and set the retry timeout period to further ensure the retry validity and stability of the retry process.

  • Both use the command design mode, through the delegate retry object to complete the corresponding logical operation, at the same time internal encapsulation to achieve the retry logic.

  • Spring-retry and Guava-Retry tools are thread-safe retries that support logical retry in concurrent service scenarios. Both approaches are elegant retry strategies. Spring-retry configuration is simpler and functions are relatively simple. Guava is a boutique Java library from Google, and guava-Retry is very powerful. Compared with spring-retry, it is more selective in determining whether to Retry and can be used as a supplement to spring-retry.

Graceful retry applies to scenarios

Unstable dependency scenarios exist in the functional logic. Retry is required to obtain the expected result or re-execution of the logic does not end immediately. Such as remote interface access, data load access, data upload verification and so on.

For exception scenarios, retry is required and normal logic and retry logic are decoupled.

Retry schemes can also be considered for scenarios that require data-media-based interactions and wish to test execution logic through retry polling.