1. 程式人生 > >Spring異常重試框架Spring Retry

Spring異常重試框架Spring Retry

value img bind 框架 項目 slf4 cti 延遲 oot

Spring Retry支持集成到Spring或者Spring Boot項目中,而它支持AOP的切面註入寫法,所以在引入時必須引入aspectjweaver.jar包。

快速集成的代碼樣例:

@Configuration
@EnableRetry
public class Application {

    @Bean
    public Service service() {
        return new Service();
    }

}

@Service
class Service {
    @Retryable(RemoteAccessException.
class) public service() { // ... do something } }

下面是基於Spring Boot項目的集成步驟:

POM:

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

Service:

package com.jsoft.springboottest.springboottest1;

import java.time.LocalTime;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.springframework.remoting.RemoteAccessException; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Recover; import org.springframework.retry.annotation.Retryable; import org.springframework.stereotype.Service; @Service public class RemoteService { private final static Logger logger = LoggerFactory.getLogger(RemoteService.class); @Retryable(value = { RemoteAccessException.class }, maxAttempts = 3, backoff = @Backoff(delay = 5000l, multiplier = 1)) public void call() throws Exception { logger.info(LocalTime.now()+" do something..."); throw new RemoteAccessException("RPC調用異常"); } @Recover public void recover(RemoteAccessException e) { logger.info(e.getMessage()); } }

@Retryable註解

被註解的方法發生異常時會重試

  • value:指定發生的異常進行重試
  • include:和value一樣,默認空,當exclude也為空時,所有異常都重試
  • exclude:指定異常不重試,默認空,當include也為空時,所有異常都重試
  • maxAttemps:重試次數,默認3
  • backoff:重試補償機制,默認沒有

@Backoff註解

  • delay:指定延遲後重試
  • multiplier:指定延遲的倍數,比如delay=5000l,multiplier=2時,第一次重試為5秒後,第二次為10秒,第三次為20秒

@Recover

當重試到達指定次數時,被註解的方法將被回調,可以在該方法中進行日誌處理。需要註意的是發生的異常和入參類型一致時才會回調。

Controller:

package com.jsoft.springboottest.springboottest1.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.jsoft.springboottest.springboottest1.RemoteService;

@RestController
public class TestController {
    
    @Autowired
    private RemoteService remoteService;
    
    @RequestMapping("/show")
    public String show(){
        try {
            remoteService.call();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            //e.printStackTrace();
        }
        return "Hello World";        
    }
}

App:

package com.jsoft.springboottest.springboottest1;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.retry.annotation.EnableRetry;

/**
 * Hello world!
 *
 */
@SpringBootApplication
@EnableRetry
public class App 
{
    public static void main( String[] args )
    {
        SpringApplication.run(App.class, args);
    }
}

效果:

技術分享

說明:

1、使用了@Retryable的方法不能在本類被調用,不然重試機制不會生效。也就是要標記為@Service,然後在其它類使用@Autowired註入或者@Bean去實例才能生效。

2、要觸發@Recover方法,那麽在@Retryable方法上不能有返回值,只能是void才能生效。

3、使用了@Retryable的方法裏面不能使用try...catch包裹,要在發放上拋出異常,不然不會觸發。

4、在重試期間這個方法是同步的,如果使用類似Spring Cloud這種框架的熔斷機制時,可以結合重試機制來重試後返回結果。

5、Spring Retry不只能註入方式去實現,還可以通過API的方式實現,類似熔斷處理的機制就基於API方式實現會比較寬松。

示例代碼:https://github.com/easonjim/5_java_example/tree/master/springboottest/springboottest3

參考:

http://blog.csdn.net/u014513883/article/details/52371198(以上內容部分轉自此篇文章)

https://github.com/spring-projects/spring-retry(官網)

http://www.jianshu.com/p/314059943f1c

http://www.broadview.com.cn/article/233(熔斷重試)

Spring異常重試框架Spring Retry