我的问题与微服务中的异常行为有关。假设我们有一个微服务(假设是微服务a),它有一个控制器通知注释类来处理所有异常。
我的微服务a也在调用另一个微服务(假设是微服务b)。假设此调用发生在带有@CircuitBreaker(name="myService", fallback="myFallbackMethod")
注释的服务层方法中因此,如果我在成功调用微服务b之后引入任何运行时异常,回退方法会执行吗,或者@ControllerAdvice
注释类中存在的@ExceptionHandler
注释方法会执行吗?
附加poc片
//Microservice-A
package com.example.iplservice.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.iplservice.feign.MyFeignClient;
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
@RestController
@RequestMapping("ipl")
public class IplController {
@Value("${ipl.team}")
private String iplTeam;
@Autowired
private Environment env;
@Autowired
private MyFeignClient myFeignClient;
@GetMapping("/team/hello")
@CircuitBreaker(name = "cricketService", fallbackMethod = "getHelloFallBack")
public ResponseEntity < String > getHello() {
String body = myFeignClient.getHello().getBody();
//introducing an error here!!
int a = 2 / 0;
System.out.println("-----------------" + a);
return ResponseEntity.ok("Hello " + iplTeam + " : " + env.getProperty("local.server.port") + " : Called : " + body);
}
}
//Microservice-A ends
//Microservice-A Controller Advice
package com.example.iplservice.excetion;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
@ControllerAdvice
public class CricketExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity < String > handleGenericException(Exception ex) {
return ResponseEntity.ok("Error From Controller Advice : " + ex.getMessage());
}
}
//Microservice-A Controller Advice ends
//Microservice-B
package com.example.cricketersdetailservice.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.core.env.Environment;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RefreshScope
@RequestMapping("/cricket")
public class CricketController {
@Value("${cricketer.team}")
private String teamName;
@Autowired
private Environment env;
@GetMapping("/team/hello")
public ResponseEntity < String > getHello() {
return ResponseEntity.ok("Hello " + teamName + " : " + env.getProperty("local.server.port"));
}
}
//Microservice-B ends
正如我在代码中看到的,回退方法将被触发。即使对微服务B的调用成功,Circuit Breaker也会监视getHello
方法上发生的每个异常。
如果你想改变这个行为,有一些选择:
- 仅用断路器装饰虚拟客户端方法调用
- 分隔对新方法的伪客户端调用,并使用
@CircuitBreaker
注释该方法 - 配置断路器只观察由伪客户端抛出的特定异常
查看此处和此处的resilience4j文档