spring retry 使用
1. 场景
系统方法调用时无状态的,同时因为网络原因,或者系统暂时故障,进行的重试
2. maven 依赖
<projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.dalong.spring.io</groupId>
<artifactId>springretrydemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.2.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>1.1.5.RELEASE</version><!--$NO-MVN-MAN-VER$ -->
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.geronimo.bundles</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.8_2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version><!--$NO-MVN-MAN-VER$ -->
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
3. 定义 service 并标注retry 策略
注解驱动,方法驱动
@Service
publicclassFirstService{
@Retryable(value=RemoteAccessException.class,maxAttempts=3,backoff=@Backoff(delay =5000l,multiplier =1))
publicString service(String value){
// ... do something
System.out.println("do something...");
if(null==value||"".equals(value)){
thrownewRemoteAccessException("RPC调用异常");
}
else{
return"dalong demo info";
}
}
@Recover
publicString recover(RemoteAccessException e){
// ... panic
System.out.println(e.getMessage());
System.out.println("rong method");
return e.getMessage();
}
}
使用retrytemplate
@Service
publicclassMyService2{
@Autowired
publicUserOperator userOperator;
publicUserInfo getUserinfo()throwsTimeoutException{
RetryTemplate template =newRetryTemplate();
TimeoutRetryPolicy policy =newTimeoutRetryPolicy();
policy.setTimeout(1000L);
template.setRetryPolicy(policy);
UserInfo result = template.execute(newRetryCallback<UserInfo,TimeoutException>(){
@Override
publicUserInfo doWithRetry(RetryContext context)throwsTimeoutException{
// TODO Auto-generated method stub
UserInfo info =null;
info = userOperator.getUserinfo();
return info;
}
},newRecoveryCallback<UserInfo>(){
@Override
publicUserInfo recover(RetryContext context)throwsException{
// TODO Auto-generated method stub
UserInfo inf =newUserInfo();
inf.setDate(newDate());
inf.setAge(333);
inf.setInfo("default");
return inf;
}
});
return result;
}
}
UserOperator 服务
@Service
publicclassUserOperator{
publicUserInfo getUserinfo()throwsTimeoutException{
UserInfo info =newUserInfo();
info.setDate(newDate());
info.setAge(333);
info.setInfo("dddddd");
try{
Thread.sleep(2000);
}catch(InterruptedException e){
// TODO Auto-generated catch block
e.printStackTrace();
thrownewTimeoutException("timeout");
}
return info;
}
}
4. rest api 调用
@Autowired
publicMyService2 myService2;
@RequestMapping(value ="/user", method =RequestMethod.GET)
publicObject getuser()throwsTimeoutException{
UserInfo info =null;
info = myService2.getUserinfo();
return info;
// return "this is demo";
}
5. 类似的解决方案
netflix 公司的hystrix ,目前spring cloud 已经进行了集成封装,也可以单独进行使用。
6. 重试策略的说明
- org.springframework.retry.policy.SimpleRetryPolicy
该策略定义了对指定的异常进行若干次重试。默认情况下,对Exception异常及其子类重试3次。如果创建SimpleRetryPolicy并指定重试异常map,可以选择性重试或不进行重试。下面的代码定义了对TimeOutException进行重试 - org.springframework.retry.policy.NeverRetryPolicy
执行一次待执行操作,若出现异常后不进行重试。 - org.springframework.retry.policy.AlwaysRetryPolicy
异常后一直重试直到成功。 - org.springframework.retry.policy.TimeoutRetryPolicy
在执行execute方法时从open操作开始到调用TimeoutRetryPolicy的canRetry方法这之间所经过的时间。这段时间未超过TimeoutRetryPolicy定义的超时时间,那么执行操作,否则抛出异常。 -
org.springframework.retry.policy.ExceptionClassifierRetryPolicy
根据产生的异常选择重试策略。
-
org.springframework.retry.policy.CompositeRetryPolicy
用户指定一组策略,随后根据optimistic选项来确认如何重试。