Spring異常重試框架Spring Retry
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