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:
RetryerBuilder
Is 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.RetryerBuilder
The retry source supports Exception Exception objects and custom assertion objects throughretryIfException
和retryIfResult
Settings, supports multiple and compatible.retryIfException
Runtime and CHECKED exceptions are retried, but errors are not retried.retryIfRuntimeException
We only retry runtime exceptions. Checked and ERROR exceptions are not retried.retryIfExceptionOfType
Allows us to retry only if a specific exception occurs, such asNullPointerException and
IllegalStateException ‘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…