Java programming Retry Mechanism instance details, javaretry Retry details

Source: Internet
Author: User

Java programming Retry Mechanism instance details, javaretry Retry details

This article mainly describes the example of the Retry Mechanism for Java programming and shares the relevant code examples. The small editor thinks it is quite good and has some reference value. If you need it, you can refer to it.

1. business scenarios

You need to implement a function in the application: You need to upload data to the remote storage service and perform other operations when the processing is successful. This function is not complex and involves two steps: the first step is to call the remote Rest service logic to encapsulate the processing method to return the processing result; the second step is to get the result of the first step or capture exceptions, if an error or exception occurs, retry the upload logic. Otherwise, proceed with the logical operation.

2. Evolution of conventional solutions
1) try-catch-redo simple retry mode:

Based on the packaging of the normal upload logic, determine whether to retry the returned results or listen for abnormal decisions, and to solve the invalid execution of instant retry (assuming that the exception is caused by unstable external execution ), sleep takes a certain delay to re-execute the function logic.

Public void commonRetry (Map <String, Object> dataMap) throws InterruptedException {Map <String, Object> paramMap = Maps. newHashMap (); paramMap. put ("tableName", "creativeTable"); paramMap. put ("ds", "20160220"); paramMap. put ("dataMap", dataMap); boolean result = false; try {result = uploadToOdps (paramMap); if (! Result) {Thread. sleep (1000); uploadToOdps (paramMap); // One retry} catch (Exception e) {Thread. sleep (1000); uploadToOdps (paramMap); // One retry }}
2) try-catch-redo-retry strategy retry mode:

The above scheme may still be ineffective. To solve this problem, try to increase the retrycount and the interval of the Retry interval to increase the possibility of retry effectiveness.

Public void commonRetry (Map <String, Object> dataMap) throws InterruptedException {Map <String, Object> paramMap = Maps. newHashMap (); paramMap. put ("tableName", "creativeTable"); paramMap. put ("ds", "20160220"); paramMap. put ("dataMap", dataMap); boolean result = false; try {result = uploadToOdps (paramMap); if (! Result) {reuploadToOdps (paramMap, 1000L, 10); // multiple retry delays} catch (Exception e) {reuploadToOdps (paramMap, 1000L, 10 ); // multiple retry delays }}

Solution 1 and solution 2 have a problem: the normal logic and retry logic are strongly coupled. The retry logic is very dependent on the execution results of the normal logic and is triggered by passive retry of the expected results of the normal logic, the root cause of Retry is often overwhelmed by complicated logic, which may lead to inconsistent understanding of the problems to be solved by the retry logic in subsequent O & M. The retry correctness is difficult to guarantee and is not conducive to O & M. The reason is that the retry design relies on hypothetical tests with normal logic exceptions or the source of retry.

3. Try an elegant retry solution:

Is there a solution that can be referenced to achieve normal logic and retry logic decoupling, while also providing a standardized solution for retry logic? The answer is: the retry tool based on the proxy design mode. We try to use the corresponding tool to reconstruct the above scenario.

1) The application command design mode decouples the normal and retry logic:

The specific definition of the command design pattern is not elaborated. This scheme mainly focuses on the Command pattern, which can complete the interface operation logic through the execution object, and internally encapsulate and process the retry logic without exposing implementation details, for callers, the normal logic is executed to achieve the goal of decoupling. For details, refer to the function implementation. (Class graph structure)

IRetry defines the upload and retry interfaces. Its implementation class OdpsRetry encapsulates the ODPS upload logic, and encapsulates the Retry Mechanism and retry policy. At the same time, use the recover method to complete the restoration operation.

However, our caller LogicClient does not need to pay attention to retries. The Retryer implements the agreed interface function through the Retryer, And the Retryer must respond to and process the retry logic, retryer's specific retry processing is handed over to the implementation class OdpsRetry of the real IRtry interface. By using the command mode, the separation of the normal logic and the retry logic is achieved elegantly, and the separation of the normal logic and the retry logic is achieved through the construction of the re-subject role, so that the retry can have better scalability.

2) spring-retry specifications for normal and retry Logic

Spring-retry is an open-source toolkit. Currently, the available version is 1.1.2.RELEASE. This tool customizes retry operation templates and allows you to Set retry policies and rollback policies. At the same time, retry the execution instance to ensure thread security. The specific scenario is as follows:

Public void upload (final Map <String, Object> map) throws Exception {// create a retry template instance RetryTemplate retryTemplate = new RetryTemplate (); // set a retry policy, set the number of retries (SimpleRetryPolicy policy = new SimpleRetryPolicy (3, Collections. <Class <? Extends Throwable>, Boolean> singletonMap (Exception. class, true); // sets the retry rollback operation policy. It mainly sets the Retry Interval FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy (); fixedBackOffPolicy. setBackOffPeriod (100); retryTemplate. setRetryPolicy (policy); retryTemplate. setBackOffPolicy (fixedBackOffPolicy); // use RetryCallback to retry the callback instance to encapsulate the normal logic. The first execution and retry execution are all executed using this logic final RetryCallback <Object, exception> retryCallback = new RetryCallback <Object, Exception> () {// context Convention for RetryContext retry operations, unified spring-try to wrap public Object doWithRetry (RetryContext context) throws Exception {System. out. println ("do some thing"); Exception e = uploadToOdps (map); System. out. println (context. getRetryCount (); throw e; // note that the retry source is returned through Exception }}; // use RecoveryCallback to terminate the retry process normally or exit the restore instance after the Retry limit is reached. final RecoveryCallback <Object> recoveryCallback = new RecoveryCallback <Object> () {public Object recover (RetryContext context) throws Exception {System. out. println ("do recory operation"); return null ;}}; try {// The retryTemplate executes the execute method to start logical execution of retryTemplate.exe cute (retryCallback, recoveryCallback );} catch (Exception e) {e. printStackTrace ();}}

After a simple analysis of the case code, RetryTemplate assumes the role of the retry executor. It can be used to set the SimpleRetryPolicy (retry policy, retry upper limit, and retry source entity), FixedBackOffPolicy (fixed rollback policy, set the interval for executing the retry rollback ). RetryTemplate submits and executes operations through execute. You need to prepare two types of instances, RetryCallback and RecoveryCallback. The former corresponds to the retry callback logic instance, which encapsulates normal functional operations, recoveryCallback implements the recovery instance after the entire operation is completed.

The execute of RetryTemplate is thread-safe. The implementation logic uses ThreadLocal to save the RetryContext execution context of each execution instance.

Although the Spring-retry tool can implement retry elegantly, there are two unfriendly designs: one is that the retry object is limited to the Throwable subclass, the retry is designed on the premise of capturing functional exceptions, but we want to rely on a data object entity as the retry object, but the Sping-retry framework must be forcibly converted to the Throwable subclass. The other is that the asserted object at the retry source uses the Exception instance of doWithRetry, which does not conform to the normal internal assertion return design.

Spring Retry advocates retrying methods in Annotation mode. The Retry logic is executed synchronously. The Retry "failure" is for Throwable, if you want to determine whether or not to retry based on a certain status of the returned value, you may only need to determine the returned value by yourself and then explicitly throw an exception.

Spring's Retry Abstraction

"Abstraction" is essential to every programmer. For me with equal qualifications, there is no better way to progress than to imitate and understand the excellent source code. To this end, I have rewritten its core logic... let's take a look at Spring Retry's abstraction of "Retry.

Spring retryrelated interface .jpg

  • RetryCallback)
  • RecoverCallback: encapsulate the business logic that you need to execute after multiple retries fail (doSthWhenStillFail in the preceding Section)
  • RetryContext: context in the Retry context. It can be used to pass a parameter or state between multiple retries, retries, and recovers (passing a parameter between dosomething or dosomething and doSthWhenStillFail)
  • RetryOperations: defines the basic framework (Template) for "retry". You must pass in RetryCallback. Optional, RecoveryCallback;
  • RetryListener: a typical "listener" that notifies "listeners" at different retry stages (for example, notifications during dosomething, wait, and other stages)
  • RetryPolicy: retry policy or condition. You can simply retry multiple times or specify the timeout value (someCondition in the preceding section)
  • BackOffPolicy: A retry rollback policy. When an exception occurs in the execution of the business logic. If you need to retry, we may need to wait for a while (the server may be too busy, and the server may be dragged down if you try again without interval). Of course, this time can be 0 or fixed, it can be random (see the rollback policy in tcp's congestion control algorithm ). The rollback policy is shown in the preceding section as wait ();
  • RetryTemplate: the specific implementation of RetryOperations, combined with RetryListener [], BackOffPolicy, RetryPolicy.
3) guava-retryer separation of normal and retry Logic

Similar to spring-retry, the Guava retryer tool encapsulates normal logic retries by defining the subject's role. However, Guava retryer has a better policy definition. Based on its support for retries and retry frequency control, it is compatible with the retry Source Definition of multiple exceptions or custom object objects, giving the retry function more flexibility. Guava Retryer is also thread-safe. The Calling logic of the entry uses the call method of Java. util. concurrent. Callable. The sample code is as follows:

Public void uploadOdps (final Map <String, Object> map) {// RetryerBuilder creates a retry instance retryer. You can set retry sources and support multiple retry sources, you can configure the number of retries or the retry timeout time, and configure the wait interval Retryer <Boolean> retryer = RetryerBuilder. <Boolean> newBuilder (). retryIfException (). // set the retryIfResult (new Predicate <Boolean> () {// set the custom segment meta retry source, @ Override public boolean apply (Boolean state) {// Note: if true is returned for this apply operation, Retry is required. return true must be distinguished from the semantics of the operation logic ;}}). withStopStrategy (StopStrategies. stopAfterAttempt (5) // set the retry time to 5 times. You can also set the retry timeout time. withWaitStrategy (WaitStrategies. fixedWait (100L, TimeUnit. MILLISECONDS )). build (); // set the Retry Interval. try {// call method is used for the retry entry. java is used. util. concurrent. callable <V> call method, so the execution is a thread-safe boolean result = retryer. call (new Callable <Boolean> () {@ Override public Boolean call () throws Exception {try {// Note: if false is returned, no Retry is required, if the return value is true, return uploadToOdps (map);} catch (Exception e) {throw new Exception (e) ;}});} catch (ExecutionException e) must be retried) {} catch (RetryException ex ){}}

Sample Code principle analysis:

RetryerBuilder is a factory creator. You can customize the retry source settings and support multiple retry sources. You can configure the number of retries or retry timeout, and configure the wait interval, create a Retryer instance for the specified subject.

RetryerBuilder's retry source supports Exception objects and custom asserted objects. It is set through retryIfException and retryIfResult, and supports multiple and compatible RetryerBuilder.

The RetryerBuilder's wait time and retry restrictions are configured using different policy classes, and the wait time feature can support no interval or fixed interval.

Retryer is an instance of the re-test. The call method is used to execute the operation logic and encapsulate the retry source operation.

Elegance, retry, commonalities, and principles

Normal and retry are elegantly decoupled. Retry an asserted condition instance or a logical exception instance is the medium for communication between the two.
Specify Retry Interval and retry difference policy, and Set retry timeout to further ensure retry validity and retry process stability.
The command design mode is used to perform logical operations by entrusting the retry object, and the retry logic is encapsulated internally.
Both Spring-tryer and guava-tryer tools are thread-safe retries, and support retry logic correctness in concurrent business scenarios.

Elegant retry scenarios

There is an unstable dependency scenario in the functional logic. Retry to obtain the expected results or retry the execution logic. For example, remote interface access, data loading access, and data upload verification.
Retry is required for exception scenarios, and the normal logic and retry logic need to be decoupled.
The retry scheme can also be considered for scenarios that require data media-based interaction and require retry round robin detection and execution logic.

Summary

The above is all the details about the Retry Mechanism instance of Java programming in this article. I hope it will be helpful to you. If you are interested, you can continue to refer to other related topics on this site. If you have any shortcomings, please leave a message. Thank you for your support!

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.