Springboot @retryable没有重试

时间:2016-07-05 20:49:50

标签: java spring maven spring-boot spring-retry

以下代码未重试。我错过了什么?

@EnableRetry
@SpringBootApplication
public class App implements CommandLineRunner
{
    .........
    .........


    @Retryable()
    ResponseEntity<String> authenticate(RestTemplate restTemplate, HttpEntity<MultiValueMap<String, String>> entity) throws Exception
    {
        System.out.println("try!");
        throw new Exception();
        //return restTemplate.exchange(auth_endpoint, HttpMethod.POST, entity, String.class);
    }

我已将以下内容添加到pom.xml中。

    <dependency>
        <groupId>org.springframework.retry</groupId>
        <artifactId>spring-retry</artifactId>
        <version>1.1.2.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>

我也试过为@Retryable提供不同的参数组合。

@Retryable(maxAttempts=10,value=Exception.class,backoff=@Backoff(delay = 2000,multiplier=2))

感谢。

8 个答案:

答案 0 :(得分:9)

对于要发现的方法的@Retryable注释,需要从初始化的上下文中正确调用它。方法是从spring上下文中调用bean还是通过其他方式调用?

如果使用SpringJunit4ClassRunner测试这是你的跑步者?

答案 1 :(得分:7)

在Spring Boot 2.0.2发行版中,我观察到@Retryable在同一个类中具有可重试和调用的方法时不起作用。在调试时发现切入点没有正确构建。现在,解决此问题的方法是,我们需要在其他类中编写该方法并调用它。

可以找到工作示例here

答案 2 :(得分:3)

我解决了。我发现如果从你试图重试的方法返回一些东西,那么@Retryable()就不起作用了。

pom.xml中的maven依赖

    <dependency>
        <groupId>org.springframework.retry</groupId>
        <artifactId>spring-retry</artifactId>
        <version>1.1.5.RELEASE</version>
    </dependency>

Spring boot Application.java

@SpringBootApplication
@EnableTransactionManagement
@EnableRetry
public class Application {

     public static void main(String[] args) throws Exception {
       SpringApplication.run(Application.class, args);
     }

}

在controller.java中

@RestController
public class JavaAllDataTypeController {

@Autowired
JavaAllDataTypeService JavaAllDataTypeService;


@RequestMapping(
        value = "/springReTryTest",
        method = RequestMethod.GET
)
public ResponseEntity<String> springReTryTest() {

    System.out.println("springReTryTest controller");

    try {
         JavaAllDataTypeService.springReTryTest();
    } catch (Exception e) {
        e.printStackTrace();
    }

    return new  ResponseEntity<String>("abcd", HttpStatus.OK);
  }

}
中的

@Service
@Transactional
public class JavaAllDataTypeService {

 // try the method 9 times with 2 seconds delay.
 @Retryable(maxAttempts=9,value=Exception.class,backoff=@Backoff(delay = 2000))
 public void springReTryTest() throws Exception {

    System.out.println("try!");
    throw new Exception();
  }

}

输出:它&#39;尝试9次然后抛出异常。

enter image description here

答案 3 :(得分:2)

它也适用于返回类型

@Service
public class RetryService {

private int count = 0;

// try the method 9 times with 2 seconds delay.
@Retryable(maxAttempts = 9, value = Exception.class, backoff = @Backoff(delay = 2000))
public String springReTryTest() throws Exception {
    count++;
    System.out.println("try!");

    if (count < 4)
        throw new Exception();
    else
        return "bla";
  }

}

答案 4 :(得分:0)

另一个选择可以是RetryTemplate

@Bean
    public RetryTemplate retryTemplate() {
        RetryTemplate retryTemplate = new RetryTemplate();

        FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy();
        fixedBackOffPolicy.setBackOffPeriod(2000l);
        retryTemplate.setBackOffPolicy(fixedBackOffPolicy);

        SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
        retryPolicy.setMaxAttempts(2);
        retryTemplate.setRetryPolicy(retryPolicy);

        return retryTemplate;
    }

retryTemplate.execute(new RetryCallback<Void, RuntimeException>() {
    @Override
    public Void doWithRetry(RetryContext arg0) {
        myService.templateRetryService();
        ...
    }
});

为我锻炼

source

答案 5 :(得分:0)

我遇到的问题与原始问题完全相同。

在我的情况下,事实证明偶然不包括spring-boot-starter-aop依赖项。将其添加到我的pom.xml后,我的@Retryable方法可以正常工作。

@Retryable方法返回值对我来说很好。

答案 6 :(得分:0)

即使我遇到了同样的问题,后来经过一些调查和研究才知道,除了方法上面的@Retryable注解,我们还需要在类上面提供@EnableRetry。这个@EnableRetry 注释可以提供在您提供了要重试的方法的同一类之上,也可以提供在主 Spring Boot 应用程序类之上。例如像这样:

@RequiredArgsConstructor
**@EnableRetry**
@Service
public class SomeService {

  **@Retryable(value = { HttpServerErrorException.class, BadRequestException.class},
      maxAttempts = maxRetry, backoff = @Backoff(random = true, delay = 1000,
                         maxDelay = 8000, multiplier = 2))**
  public <T> T get( ) throws  HttpServerErrorException, BadRequestException {
    
     //write code here which you want to retry
  }

}

我希望这能帮助您解决问题。

答案 7 :(得分:0)

对于那些想在来类中调用 @Retryable 块的人可以通过这种方式。

这里的关键不是直接调用方法,而是通过自注入bean

@Slf4j
@Service
public class RetryService {

    @Resource(name = "retryService")
    private RetryService self;

    public String getValue(String appender) {
        return self.getData(appender);
    }

    @Retryable(value = NumberFormatException.class, maxAttempts = 4, backoff = @Backoff(500))
    public String getData(String appender) {
        log.info("Calling getData");
        Integer value = Integer.parseInt(appender);
        value++;
        return value.toString();
    }

    @Recover
    public String recoverData(String appender) {
        log.info("Calling recoverData");
        return "DEFAULT";
    }

}

可以阅读更多关于使用重试的详细信息here