springboot(十四)使用spring retry

20 篇文章 0 订阅
转载:http://blog.csdn.net/u011493599/article/details/70171977

在调用第三方接口或者使用mq时,会出现网络抖动,连接超时等网络异常,所以需要重试。

1、引入jar包

  1. <dependency>  
  2.             <groupId>org.springframework.retry</groupId>  
  3.             <artifactId>spring-retry</artifactId>  
  4.         </dependency>  
  5.         <dependency>  
  6.             <groupId>org.aspectj</groupId>  
  7.             <artifactId>aspectjweaver</artifactId>  
  8.         </dependency>  
<dependency>
            <groupId>org.springframework.retry</groupId>
            <artifactId>spring-retry</artifactId>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
        </dependency>

2、模拟网络异常,创建一个异常

 

  1. package com.demo.exception;  
  2.   
  3. import lombok.Builder;  
  4. import lombok.Getter;  
  5.   
  6. /** 
  7.  * Created by huguoju on 2017/4/13. 
  8.  */  
  9. @Builder  
  10. @Getter  
  11. public class RetryException extends RuntimeException {  
  12.     private String code;  
  13.     private String message;  
  14. }  
package com.demo.exception;

import lombok.Builder;
import lombok.Getter;

/**
 * Created by huguoju on 2017/4/13.
 */
@Builder
@Getter
public class RetryException extends RuntimeException {
    private String code;
    private String message;
}

3、在Application上添加@EnableRetry开启Retry服务

  1. @EnableRetry  
  2. public class SpringbootApplication {  
@EnableRetry
public class SpringbootApplication {

4、在service模拟访问异常,抛出异常

  1. package com.demo.service.impl;  
  2.   
  3. import com.demo.exception.RetryException;  
  4. import com.demo.service.RetryService;  
  5. import lombok.extern.slf4j.Slf4j;  
  6. import org.springframework.retry.annotation.Backoff;  
  7. import org.springframework.retry.annotation.Recover;  
  8. import org.springframework.retry.annotation.Retryable;  
  9. import org.springframework.stereotype.Service;  
  10.   
  11. /** 
  12.  * Created by huguoju on 2017/4/13. 
  13.  */  
  14. @Service(“retryService”)  
  15. @Slf4j  
  16. public class RetryServiceImpl implements RetryService {  
  17.     int i=1;  
  18.     @Override  
  19.     @Retryable(value = {RuntimeException.class},maxAttempts = 4,backoff = @Backoff(delay = 1000l,multiplier = 1))  
  20.     public String retry() {  
  21.         log.info(”测试retry”);  
  22.         i++;//生产环境此处应该为调用第三方接口,判断接口返回code  
  23.         if(i==3){  
  24.             return i+“”;  
  25.         }  
  26.         RetryException retryException=RetryException.builder().code(”9999”).message(“连接超时”).build();  
  27.         throw retryException;  
  28.     }  
  29.   
  30.    
  31.     @Recover  
  32.     public String recover(RetryException e){  
  33.         log.info(e.getMessage());  
  34.         return “6”;  
  35.     }  
  36. }  
package com.demo.service.impl;

import com.demo.exception.RetryException;
import com.demo.service.RetryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;

/**
 * Created by huguoju on 2017/4/13.
 */
@Service("retryService")
@Slf4j
public class RetryServiceImpl implements RetryService {
    int i=1;
    @Override
    @Retryable(value = {RuntimeException.class},maxAttempts = 4,backoff = @Backoff(delay = 1000l,multiplier = 1))
    public String retry() {
        log.info("测试retry");
        i++;//生产环境此处应该为调用第三方接口,判断接口返回code
        if(i==3){
            return i+"";
        }
        RetryException retryException=RetryException.builder().code("9999").message("连接超时").build();
        throw retryException;
    }


    @Recover
    public String recover(RetryException e){
        log.info(e.getMessage());
        return "6";
    }
}

说明:

@Retryable:标注此注解的方法在发生异常时会进行重试
参数说明:value:抛出指定异常才会重试
          include:和value一样,默认为空,当exclude也为空时,默认所以异常
          exclude:指定不处理的异常
          maxAttempts:最大重试次数,默认3次
          backoff:重试等待策略,默认使用@Backoff,@Backoff的value默认为1000L,multiplier(指定延迟倍数)
                   默认为0,表示固定暂停1秒后进行重试,如果把multiplier设置为2,则第一次重试为1秒,第二次为
                   2秒,第三次为4秒
@Recover:用于@Retryable重试失败后处理方法,此方法里的异常一定要是@Retryable方法里抛出的异常,否则不会调用
          这个方法
5、在其他service里调用上面的service抛出异常
   
   
   
  1. @Override  
  2.     public Map testRetry() {  
  3.         Map map= Maps.newHashMap();  
  4.         String s=retryService.retry();  
  5.         if (s.equals(“3”)){  
  6.             log.info(”成功啦啦啦啦啦啦啦啦”);  
  7.         }else {  
  8.             log.info(”失败了”);  
  9.         }  
  10.         map.put(”result”,s);  
  11.         return map;  
  12.     }  
@Override
    public Map testRetry() {
        Map map= Maps.newHashMap();
        String s=retryService.retry();
        if (s.equals("3")){
            log.info("成功啦啦啦啦啦啦啦啦");
        }else {
            log.info("失败了");
        }
        map.put("result",s);
        return map;
    }

6、定义测试controller
   
   
  1. package com.demo.controller;  
  2.   
  3. import com.demo.service.RetryService;  
  4. import com.demo.service.TestService;  
  5. import com.google.common.collect.Maps;  
  6. import io.swagger.annotations.Api;  
  7. import org.springframework.beans.factory.annotation.Autowired;  
  8. import org.springframework.http.MediaType;  
  9. import org.springframework.web.bind.annotation.RequestMapping;  
  10. import org.springframework.web.bind.annotation.RequestMethod;  
  11. import org.springframework.web.bind.annotation.RestController;  
  12.   
  13. import java.util.Map;  
  14.   
  15. /** 
  16.  * Created by huguoju on 2017/4/13. 
  17.  */  
  18. @RestController  
  19. @RequestMapping(“retry”)  
  20. @Api(value = “重试机制”,tags = “重试机制”)  
  21. public class RetryController {  
  22.     @Autowired  
  23.     public TestService testService;  
  24.     @RequestMapping(value = “testRetry”,method = {RequestMethod.POST,RequestMethod.GET},produces = MediaType.APPLICATION_JSON_UTF8_VALUE)  
  25.     public Map testRetry(){  
  26.         Map map=Maps.newHashMap();  
  27.         try {  
  28.             map= testService.testRetry();  
  29.             return map;  
  30.         }catch (Exception e){  
  31.             e.printStackTrace();  
  32.             return map;  
  33.         }  
  34.     }  
  35. }  
package com.demo.controller;

import com.demo.service.RetryService;
import com.demo.service.TestService;
import com.google.common.collect.Maps;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;

/**
 * Created by huguoju on 2017/4/13.
 */
@RestController
@RequestMapping("retry")
@Api(value = "重试机制",tags = "重试机制")
public class RetryController {
    @Autowired
    public TestService testService;
    @RequestMapping(value = "testRetry",method = {RequestMethod.POST,RequestMethod.GET},produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public Map testRetry(){
        Map map=Maps.newHashMap();
        try {
            map= testService.testRetry();
            return map;
        }catch (Exception e){
            e.printStackTrace();
            return map;
        }
    }
}

访问controller,看日志输出
   
   
  1. 15:21:30 WARN  [qtp1129243682-21]  com.atomikos.icatch.imp.TransactionServiceImp - Attempt to create a transaction with a timeout that exceeds com.atomikos.icatch.max_timeout - truncating to: 300000  
  2. 15:21:30 INFO  [qtp1129243682-21]  com.atomikos.icatch.imp.BaseTransactionManager - createCompositeTransaction ( 10000000 ): created new ROOT transaction with id 10.3.5.31.tm0000100002  
  3. 15:21:30 INFO  [qtp1129243682-21]  com.demo.service.impl.RetryServiceImpl - 测试retry  
  4. 15:21:31 INFO  [qtp1129243682-21]  com.demo.service.impl.RetryServiceImpl - 测试retry  
  5. 15:21:31 INFO  [qtp1129243682-21]  com.demo.service.impl.TestServiceImpl - 成功啦啦啦啦啦啦啦啦  
  6. 15:21:31 INFO  [qtp1129243682-21]  com.atomikos.icatch.imp.CompositeTransactionImp - commit() done (by application) of transaction 10.3.5.31.tm0000100002  
15:21:30 WARN  [qtp1129243682-21]  com.atomikos.icatch.imp.TransactionServiceImp - Attempt to create a transaction with a timeout that exceeds com.atomikos.icatch.max_timeout - truncating to: 300000
15:21:30 INFO  [qtp1129243682-21]  com.atomikos.icatch.imp.BaseTransactionManager - createCompositeTransaction ( 10000000 ): created new ROOT transaction with id 10.3.5.31.tm0000100002
15:21:30 INFO  [qtp1129243682-21]  com.demo.service.impl.RetryServiceImpl - 测试retry
15:21:31 INFO  [qtp1129243682-21]  com.demo.service.impl.RetryServiceImpl - 测试retry
15:21:31 INFO  [qtp1129243682-21]  com.demo.service.impl.TestServiceImpl - 成功啦啦啦啦啦啦啦啦
15:21:31 INFO  [qtp1129243682-21]  com.atomikos.icatch.imp.CompositeTransactionImp - commit() done (by application) of transaction 10.3.5.31.tm0000100002

要测试@Recover,即一直异常,只需要把RetryServiceImpl里的if(i==3)改为if(i==6),把调用service里if(s.equals(“3”))改完if(s.equals(“6)),然后重新访问,日志:
   
   
  1. 15:26:54 WARN  [qtp1870436181-20]  com.atomikos.icatch.imp.TransactionServiceImp - Attempt to create a transaction with a timeout that exceeds com.atomikos.icatch.max_timeout - truncating to: 300000  
  2. 15:26:54 INFO  [qtp1870436181-20]  com.atomikos.icatch.imp.BaseTransactionManager - createCompositeTransaction ( 10000000 ): created new ROOT transaction with id 10.3.5.31.tm0000100003  
  3. 15:26:54 INFO  [qtp1870436181-20]  com.demo.service.impl.RetryServiceImpl - 测试retry  
  4. 15:26:55 INFO  [qtp1870436181-20]  com.demo.service.impl.RetryServiceImpl - 测试retry  
  5. 15:26:56 INFO  [qtp1870436181-20]  com.demo.service.impl.RetryServiceImpl - 测试retry  
  6. 15:26:57 INFO  [qtp1870436181-20]  com.demo.service.impl.RetryServiceImpl - 测试retry  
  7. 15:26:57 INFO  [qtp1870436181-20]  com.demo.service.impl.RetryServiceImpl - 连接超时  
  8. 15:26:57 INFO  [qtp1870436181-20]  com.demo.service.impl.TestServiceImpl - 成功啦啦啦啦啦啦啦啦  
  9. 15:26:57 INFO  [qtp1870436181-20]  com.atomikos.icatch.imp.CompositeTransactionImp - commit() done (by application) of transaction 10.3.5.31.tm0000100003  
15:26:54 WARN  [qtp1870436181-20]  com.atomikos.icatch.imp.TransactionServiceImp - Attempt to create a transaction with a timeout that exceeds com.atomikos.icatch.max_timeout - truncating to: 300000
15:26:54 INFO  [qtp1870436181-20]  com.atomikos.icatch.imp.BaseTransactionManager - createCompositeTransaction ( 10000000 ): created new ROOT transaction with id 10.3.5.31.tm0000100003
15:26:54 INFO  [qtp1870436181-20]  com.demo.service.impl.RetryServiceImpl - 测试retry
15:26:55 INFO  [qtp1870436181-20]  com.demo.service.impl.RetryServiceImpl - 测试retry
15:26:56 INFO  [qtp1870436181-20]  com.demo.service.impl.RetryServiceImpl - 测试retry
15:26:57 INFO  [qtp1870436181-20]  com.demo.service.impl.RetryServiceImpl - 测试retry
15:26:57 INFO  [qtp1870436181-20]  com.demo.service.impl.RetryServiceImpl - 连接超时
15:26:57 INFO  [qtp1870436181-20]  com.demo.service.impl.TestServiceImpl - 成功啦啦啦啦啦啦啦啦
15:26:57 INFO  [qtp1870436181-20]  com.atomikos.icatch.imp.CompositeTransactionImp - commit() done (by application) of transaction 10.3.5.31.tm0000100003


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当然可以!下面是一个简单的Spring Retry的示例代码: 首先,您需要在您的项目中添加Spring Retry的依赖。如果您使用Maven,可以在pom.xml文件中添加以下依赖项: ```xml <dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> <version>1.3.1</version> </dependency> ``` 接下来,您可以创建一个包含重试逻辑的方法: ```java import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; import org.springframework.stereotype.Component; @Component public class MyService { @Retryable(maxAttempts = 3, backoff = @Backoff(delay = 1000)) public void performOperation() throws Exception { // 模拟一个可能会失败的操作 if (Math.random() < 0.5) { throw new Exception("操作失败"); } else { System.out.println("操作成功"); } } } ``` 在上述示例中,我们使用了`@Retryable`注解来标记`performOperation`方法,表示该方法可以进行重试。`maxAttempts`属性指定最大重试次数,`backoff`属性指定重试间隔(这里设置为1秒)。 最后,您可以在其他类中调用`MyService`的方法进行重试: ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class MyApp { @Autowired private MyService myService; public static void main(String[] args) { SpringApplication.run(MyApp.class, args); } public void run() throws Exception { myService.performOperation(); } } ``` 在上述示例中,我们通过`@Autowired`注解将`MyService`注入到`MyApp`类中,并在`run`方法中调用`performOperation`方法进行重试。 这只是一个简单的示例,您可以根据自己的需求和业务逻辑进行更复杂的重试配置和操作。希望对您有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值