public class ActionContext {
private static final ThreadLocal<ActionType> ACTION_TYPE_THREAD_LOCAL = new ThreadLocal<>();
public static void set(ActionType actionType){
ACTION_TYPE_THREAD_LOCAL.set(actionType);}
public static ActionType get(){
return ACTION_TYPE_THREAD_LOCAL.get();}
public static void clear(){
ACTION_TYPE_THREAD_LOCAL.remove();}}
@Service
@Slf4j
@Getter
public class RetryService3 {
private intcount=0;
private int retryCount =0;
private int fallbackCount =0;
private int recoverCount =0;
public void clean(){
this.retryCount=0;
this.fallbackCount=0;
this.recoverCount=0;}/** * Command 请求,启动重试机制 */
@Action(type = ActionType.COMMAND)
@SmartFault(recover ="recover")
public Long retry(Long input) throws Throwable{
this.retryCount++;
return doSomething(input);}/** * Query 请求,启动Fallback机制 */
@Action(type = ActionType.QUERY)
@SmartFault(recover ="recover")
public Long fallback(Long input) throws Throwable{
this.fallbackCount++;
return doSomething(input);}
@Recover
public Long recover(Throwable e,Long input){
this.recoverCount++;
log.info("recover-{}", input);
return input;}
private Long doSomething(Long input){// 偶数抛出异常
if (count++%2==0){
log.info("Error-{}", input);
throw new RuntimeException();}
log.info("Success-{}", input);
return input;}}
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
测试代码如下:
@SpringBootTest(classes = DemoApplication.class)
public class RetryService3Test {
@Autowired
private RetryService3 retryService;
@BeforeEach
public void setup(){
retryService.clean();}
@Test
public void retry() throws Throwable{
for (int i =0; i <100; i++){
retryService.retry(i +0L);}
Assertions.assertTrue(retryService.getRetryCount()>0);
Assertions.assertTrue(retryService.getRecoverCount()==0);
Assertions.assertTrue(retryService.getFallbackCount()==0);}
@Test
public void fallback() throws Throwable{
for (int i =0; i <100; i++){
retryService.fallback(i +0L);}
Assertions.assertTrue(retryService.getRetryCount()==0);
Assertions.assertTrue(retryService.getRecoverCount()>0);
Assertions.assertTrue(retryService.getFallbackCount()>0);}}
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
运行 retry 测试,日志如下:
[main] c.g.l.c.f.smart.SmartFaultExecutor: action type is COMMAND
[main] c.g.l.faultrecovery.smart.RetryService3: Error-0[main] c.g.l.c.f.smart.SmartFaultExecutor: Retry method public java.lang.Long com.geekhalo.lego.faultrecovery.smart.RetryService3.retry(java.lang.Long) throws java.lang.Throwable use [0][main] c.g.l.faultrecovery.smart.RetryService3: Success-0
[main] c.g.l.c.f.smart.SmartFaultExecutor: action type is QUERY
[main] c.g.l.faultrecovery.smart.RetryService3: Error-0[main] c.g.l.c.f.smart.SmartFaultExecutor: recover From ERROR for method ReflectiveMethodInvocation: public java.lang.Long com.geekhalo.lego.faultrecovery.smart.RetryService3.fallback(java.lang.Long) throws java.lang.Throwable; target is of class [com.geekhalo.lego.faultrecovery.smart.RetryService3][main] c.g.l.faultrecovery.smart.RetryService3: recover-0
1.
2.
3.
4.
可见,当 action type 为 QUERY 时:
第一次调用时,触发异常,打印: Error-0
SmartFaultExecutor 执行 Fallback 策略,打印:recover From ERROR for method xxxx