When we call an interface, we may fail for network reasons and try again successfully. This is the retry mechanism.Be careful to use retries when they are not idempotent.
tips: idempotency
Idempotency is defined in HTTP/1.1 as requesting a resource once or more should have the same result for the resource itself (except for problems such as network timeouts).That is, any number of executions will have the same impact on the resource itself as one execution.
Annotation uses Spring Retry
(1) Maven dependence
<!-- Retry mechanism --> <dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> <version>1.2.4.RELEASE</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.4</version> </dependency>
(2) Configuration class add annotation @EnableRetry
@EnableRetry @Configuration public class RetryConfiguration { }
(3) Service method writing
@Retryable comment: value: Throw the specified exception before retrying include: Like value, the default is empty, so when exclude is also empty, the default is exceptional exclude: Specify an unhandled exception maxAttempts: Maximum number of retries, default 3 Backoff: Retry the wait policy, defaulting to @Backoff, @Backoff value defaulting to 1000L; multiplier (specify delay multiplier)
@Recover comment: The annotated method will be callback when the retry reaches the specified number of times The type of exception that occurs needs to be consistent with the parameters of the @Recover annotation The method of the @Retryable annotation cannot have a return value, otherwise the method of the @Recover annotation is invalid
@Service public class RetryService { private Logger logger = LoggerFactory.getLogger(RetryService.class); @Retryable(value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 2000L, multiplier = 2)) public void devide(double a, double b){ logger.info("Begin Division"); if (b == 0) { throw new RuntimeException(); } logger.info("{} / {} = {}", a, b, a / b); } @Recover public void recover() { logger.error("The dividend cannot be zero"); } }
(4) Testing
@RunWith(SpringRunner.class) @SpringBootTest public class BootdemoApplicationTests { @Autowired private RetryService retryService; private Logger logger = LoggerFactory.getLogger(BootdemoApplication.class); @Test public void retryTest() { //int count = retryService.retry(-1); retryService.retry(-1); //logger.info("inventory:"+ count); } }
Matters needing attention
- @Retryable cannot be used in this class or it will not take effect.If the direct call to execute retry mechanism will not take effect, the call to devide will take effect.
public void execute(double a, double b) throws DevideException { devide(a, b); } @Retryable(value = DevideException.class, maxAttempts = 3, backoff = @Backoff(delay = 2000L, multiplier = 2)) public void devide(double a, double b) throws DevideException { logger.info("Begin Division"); if (b == 0) { throw new DevideException("The dividend cannot be zero"); } logger.info("{} / {} = {}", a, b, a / b); }
Using @Retryable to catch exceptions without try catch is simple
This article is published by blog OpenWrite Release!