首页 > 解决方案 > 弹性4j断路器更改回退方法返回类型比实际调用的方法返回类型

问题描述

我正在尝试学习 Spring Boot 微服务。现在,如果我的任何被调用服务关闭,我正在尝试使用弹性 4j 实现断路器。

如果我将回退方法返回类型设置为与实际方法返回类型一样,则它可以正常工作,但我无法显示我的服务已关闭的信息。因为它然后在对象的字段中发送响应 null 。但是,如果我在实际方法中将返回类型更改为 String 并且在回退中,那么我将无法将对象值作为 JSON 获取。

是否可以使用我的后备方法返回字符串Branch service is down!..,如果可以,则从实际调用的方法中获取对象值作为 JSON?我的尝试如下:

我的控制器方法:

@GetMapping("/getById/{id}")
@CircuitBreaker(name = "default", fallbackMethod = "employeeFallback")
public ResponseModelEmployee getEmployee(@PathVariable("id") Long id) {
    return employeeService.findByEmployeeId(id);
}

我在控制器中的后备方法:

public ResponseModelEmployee employeeFallback(Long id, Exception ex) {
        return new ResponseModelEmployee();
    }

我从控制器调用的服务方法:

public ResponseModelEmployee findByEmployeeId(Long id) {
        ResponseModelEmployee empDetails = new ResponseModelEmployee();
        ...
        Branch branch = restTemplate.getForObject("http://BRANCH-SERVICE/branch/getById/" +
                employee.get().getBranchId(),
                Branch.class);

        ...

        return empDetails;
    }

我的愿望方法作为后备:

public String employeeFallback(Long id, Exception ex) {
        return "Branch Service is down";
    }

如果我将我的期望方法设置为回退,那么它会给出以下错误:

java.lang.NoSuchMethodException: class com.example.employee.VO.ResponseModelEmployee class com.example.employee.controller.EmployeeController.employeeFallback(class java.lang.Long,class java.lang.Throwable) at io.github.resilience4j.fallback.FallbackMethod.create(FallbackMethod.java:92) ~[resilience4j-spring-1.7.0.jar:1.7.0] ....

标签: spring-bootcircuit-breakerresilience4j

解决方案


Resilence4j 期望回退方法具有与实际方法相同的返回类型。 文档说:

重要的是要记住,后备方法应该放在同一个类中,并且必须具有相同的方法签名,只有一个额外的目标异常参数)。

如果有多个 fallbackMethod 方法,将调用最接近匹配的方法,例如:如果尝试从 NumberFormatException 中恢复,则会调用签名为 String fallback(String parameter, IllegalArgumentException exception)} 的方法。

只有当多个方法具有相同的返回类型并且您想一劳永逸地为它们定义相同的回退方法时,您才能使用异常参数定义一个全局回退方法。

因此,您不能直接将返回类型更改为其他类型。您可以尝试一些建议:

  • @CircuitBreaker将和添加fallback到服务方法。

  • 将服务方法和回退方法的返回类型更改为Object.

  • 另一种方法是,您可以保持返回类型不变,但将String类型消息对象添加到响应模型ResponseModelEmployee。然后在回退期间为其设置消息字符串。

  • 另一种解决方案可能是从进行 rest 调用的方法中返回 ResponseEntity,并在回退方法中使用 ResponseEntity<?> 作为响应对象。


推荐阅读