springboot(十四)使用spring retry

首页 / 新闻资讯 / 正文

First Vector Graphic

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

1、引入jar包

<dependency> 			<groupId>org.springframework.retry</groupId> 			<artifactId>spring-retry</artifactId> 		</dependency> 		<dependency> 			<groupId>org.aspectj</groupId> 			<artifactId>aspectjweaver</artifactId> 		</dependency>

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

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服务

@EnableRetry public class SpringbootApplication {

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

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抛出异常
@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
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,看日志输出

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)),然后重新访问,日志:

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