Writing in the front

In everyday development, we often come across scenarios where we need to invoke external services and interfaces. External services are generally unreliable for callers, especially in the case of poor network environment, network jitter is easy to lead to abnormal situations such as request timeout, at this time, it is necessary to use failure retry strategy to call API interface again to obtain. Retry policies are also widely used in service governance, with periodic checks to see if a service is Active.

Guava Retrying is a flexible and convenient retry component that includes a variety of retry strategies and is easy to extend.

In the words of the author:

This is a small extension to Google’s Guava Library to allow for the creation of different retrying strategies for an additional system arbitrary function call, such as something that talks to a remote service with flaky uptime.

With Guava-Retrying you can customize how you want to perform retries. You can also monitor the results and behavior of each retry. Most importantly, the Guava-style retries are really handy.

Code sample

  • The introduction of Guava – retry
<guava-retry.version>2.0.0</guava-retry.version>
<dependency>
      <groupId>com.github.rholder</groupId>
      <artifactId>guava-retrying</artifactId>
      <version>${guava-retry.version}</version>
</dependency>Copy the code
  • Define methods that implement the Callable interface so that Guava Retryer can call
/ * * *@descUpdate the agent interface *@author jianzhang11
    * @dateBetter 2017/3/31 * /
   private static Callable<Boolean> updateReimAgentsCall = new Callable<Boolean>() {
       @Override
       public Boolean call() throws Exception {
           String url = ConfigureUtil.get(OaConstants.OA_REIM_AGENT);
           String result = HttpMethod.post(url, new ArrayList<BasicNameValuePair>());
           if(StringUtils.isEmpty(result)){
              throw new RemoteException("Abnormal interface for obtaining OA reimbursable agent");
           }
           List<OAReimAgents> oaReimAgents = JSON.parseArray(result, OAReimAgents.class);
           if(CollectionUtils.isNotEmpty(oaReimAgents)){
               CacheUtil.put(Constants.REIM_AGENT_KEY,oaReimAgents);
               return true;
           }
           return false; }};Copy the code
  • Define the Retry object and set the related policies
Retryer<Boolean> retryer = RetryerBuilder
                .<Boolean>newBuilder()
                // Runtime and CHECKED exceptions will be retried, but errors will not be retried.
                .retryIfException()
                // Return false and retry
                .retryIfResult(Predicates.equalTo(false))
                // Reset the policy
                .withWaitStrategy(WaitStrategies.fixedWait(10, TimeUnit.SECONDS))
                // Number of attempts
                .withStopStrategy(StopStrategies.stopAfterAttempt(3))
                .build();
 
        try {
            retryer.call(updateReimAgentsCall);
        } catch (ExecutionException e) {
// e.printStackTrace();
        } catch (RetryException e) {
            logger.error("Update agent is abnormal, need to send a reminder email");
        }Copy the code

Use Guava Retryer’s elegant implementation retune method in three simple steps. Here’s how:

  • RetryerBuilderIs a Factory creator, you can customize the retry source and can support multiple retry sources, you can configure the retry times or retry timeout, and you can configure the wait time interval, create the retry retry instance.
  • RetryerBuilderThe retry source supports Exception Exception objects and custom assertion objects throughretryIfExceptionretryIfResultSettings, supports multiple and compatible.
  • retryIfExceptionRuntime and CHECKED exceptions are retried, but errors are not retried.
  • retryIfRuntimeExceptionWe only retry runtime exceptions. Checked and ERROR exceptions are not retried.
  • retryIfExceptionOfTypeAllows us to retry only if a specific exception occurs, such asNullPointerException andIllegalStateException ‘are Runtime exceptions, including custom errors

Such as:

.retryIfExceptionOfType(Error.class)// Retry only when an error is raisedCopy the code

Of course, we can retry only if the specified exception occurs, such as:

.retryIfExceptionOfType(IllegalStateException.class)  
.retryIfExceptionOfType(NullPointerException.class)Copy the code

Or you can do it through Predicate

.retryIfException(Predicates.or(Predicates.instanceOf(NullPointerException.class),  
                Predicates.instanceOf(IllegalStateException.class)))Copy the code

RetryIfResult specifies that your Callable method retries when it returns a value, as in

// Return false and retry
.retryIfResult(Predicates.equalTo(false))  
// Retry only after _error
.retryIfResult(Predicates.containsPattern("_error$"))  Copy the code

After a retry, if we need to do some extra processing, like send an alarm email or something, then we can use RetryListener. After each retry, Guava – Retrying automatically calls back the listener we registered. Multiple RetryListeners can be registered and will be invoked in the order in which they are registered.

import com.github.rholder.retry.Attempt;  
import com.github.rholder.retry.RetryListener;  
  
import java.util.concurrent.ExecutionException;  
  
public class MyRetryListener<Boolean> implements RetryListener {@Override  
    public <Boolean> void onRetry(Attempt<Boolean> attempt) {  
  
        // The number of retries (note: the first retry is actually the first call)
        System.out.print("[retry]time=" + attempt.getAttemptNumber());  
  
        // The delay from the first retry
        System.out.print(",delay=" + attempt.getDelaySinceFirstAttempt());  
  
        // Retry result: abnormal termination or normal return
        System.out.print(",hasException=" + attempt.hasException());  
        System.out.print(",hasResult=" + attempt.hasResult());  
  
        // What causes the exception
        if (attempt.hasException()) {  
            System.out.print(",causeBy=" + attempt.getExceptionCause().toString());  
        } else {  
            // The result of normal return
            System.out.print(",result=" + attempt.getResult());  
        }  
  
        // Bad Practice: added additional exception handling code
        try {  
            Boolean result = attempt.get(a);System.out.print(",rude get=" + result);  
        } catch (ExecutionException e) {  
            System.err.println("this attempt produce exception." + e.getCause().toString());  
        }  
  
        System.out.println();  
    }  
} Copy the code

Next specify the listener in the Retry object:

.withRetryListener(new MyRetryListener< > ())Copy the code

References:

Blog.csdn.net/aitangyong/…

Segmentfault.com/a/119000000…

Blog.csdn.net/aitangyong/…

Baijiahao.baidu.com/s?id=157532…

www.cnblogs.com/jianzh5/p/6…