Java Feign 客户端后备 - 无法调用后备

Posted

技术标签:

【中文标题】Java Feign 客户端后备 - 无法调用后备【英文标题】:Java Feign client Fallback - can't call fallback 【发布时间】:2020-07-27 05:54:27 【问题描述】:

我正在尝试理解Feign客户端在Java中的工作,并在出现错误时调用Fallback,我遇到了一些困难。 我写了一个最简单的例子来理解它是如何工作的,但似乎我很困惑。 请帮助我了解我的错误在哪里。

我还在 github 上发布了这个示例,以使其更方便: https://github.com/ksereda/feign-fallback-example

client通过Feign调用service-one,收到字符串“Get String from SERVICE-ONE”。

сlient也通过Feign调用service-two,得到字符串“Get String from SERVICE-TWO”。

先决条件: 在 service-two 不可用的情况下,client 必须调用指示对 service-three 的调用的 Fallback 类,而不是“从 SERVICE-TWO 获取字符串”客户端应该从 service-3 获取“从 SERVICE-THREE 获取字符串”

Service-twoservice-three是一样的,只是返回的字符串不同。

服务一码:

@RestController
@RequestMapping("/")
public class OneController 

    Logger logger = Logger.getLogger(OneController.class.getName());

    @GetMapping("/getStringFromServiceOne")
    public String getString() 
        logger.info("Get String from SERVICE-ONE");
        return "Get String from SERVICE-ONE";
    


服务二代码:

@RestController
@RequestMapping("/")
public class TwoController 

    Logger logger = Logger.getLogger(TwoController.class.getName());

    @GetMapping("/getStringFromServiceTwo")
    public String getString() 
        logger.info("Get String from SERVICE-TWO");
        return "Get String from SERVICE-TWO";
    


服务三码:

@RestController
@RequestMapping("/")
public class ThreeController 

    Logger logger = Logger.getLogger(ThreeController.class.getName());

    @GetMapping("/getStringFromServiceThree")
    public String getString() 
        logger.info("Get String from SERVICE-THREE");
        return "Get String from SERVICE-THREE";
    


客户端代码:

控制器:

@RestController
@RequestMapping("/")
public class ClientController 

   Logger logger = Logger.getLogger(ClientController.class.getName());

    @Autowired
    private ServiceOneFeignClient serviceOneFeignClient;

    @Autowired
    private ServiceTwoFeignClient serviceTwoFeignClient;

    @RequestMapping(path = "/getDataFromServiceOneByFeign")
    public String getDataFromServiceOne() 
        String result = serviceOneFeignClient.getString();
        logger.info("Calling through Feign Client");
        return result;
    

    @RequestMapping(path = "/getDataFromServiceTwoByFeign")
    public String getDataFromServiceTwo() 
        String result = serviceTwoFeignClient.getString();
        logger.info("Calling through Feign Client");
        return result;
    


假装1:

@FeignClient(name = "service-one", url = "http://localhost:8081/")
public interface ServiceOneFeignClient 

    @GetMapping("/getStringFromServiceOne")
    String getString();


和 Feign 2:

@FeignClient(name = "service-two", url = "http://localhost:8082/", fallback = Fallback.class)
public interface ServiceTwoFeignClient 

    @GetMapping("/getStringFromServiceTwo")
    String getString();


和 Feign 3:

@FeignClient(name = "service-three", url = "http://localhost:8083/")
public interface ServiceThreeFeignClient 

    @GetMapping("/getStringFromServiceThree")
    String getString();


主类:

@SpringBootApplication
@EnableFeignClients
@EnableCircuitBreaker
@EnableHystrix
public class ClientApplication 

    public static void main(String[] args) 
        SpringApplication.run(ClientApplication.class, args);
    


和 application.yml 文件

server:
  port: 8070

feign:
  hystrix:
    enabled: true

我在这里创建了 Fallback 类

@Component
public class Fallback implements ServiceThreeFeignClient 

    @Override
    public String getString() 
        System.out.println("Called MOVIE-SERVICE with Fallback class!");
        return new String("FALLBACK STRING");
    


如果 service-two 不可用,我想在这里调用 service-three

但是当我启动我的应用程序时,我立即得到一个错误:

Caused by: java.lang.IllegalStateException: Incompatible fallback instance. Fallback/fallbackFactory of type class com.example.client.service.Fallback is not assignable to interface com.example.client.service.ServiceTwoFeignClient for feign client service-two
    at org.springframework.cloud.openfeign.HystrixTargeter.getFromContext(HystrixTargeter.java:86) ~[spring-cloud-openfeign-core-2.1.1.RELEASE.jar:2.1.1.RELEASE]
    at org.springframework.cloud.openfeign.HystrixTargeter.targetWithFallback(HystrixTargeter.java:70) ~[spring-cloud-openfeign-core-2.1.1.RELEASE.jar:2.1.1.RELEASE]
    at org.springframework.cloud.openfeign.HystrixTargeter.target(HystrixTargeter.java:46) ~[spring-cloud-openfeign-core-2.1.1.RELEASE.jar:2.1.1.RELEASE]
    at org.springframework.cloud.openfeign.FeignClientFactoryBean.getTarget(FeignClientFactoryBean.java:284) ~[spring-cloud-openfeign-core-2.1.1.RELEASE.jar:2.1.1.RELEASE]
    at org.springframework.cloud.openfeign.FeignClientFactoryBean.getObject(FeignClientFactoryBean.java:247) ~[spring-cloud-openfeign-core-2.1.1.RELEASE.jar:2.1.1.RELEASE]
    at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:171) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]

我明白他写的是什么:我必须指出

implements ServiceTwoFeignClient

改为

implements ServiceThreeFeignClient

但是如果服务二不可用,我想调用服务三。

我不明白该怎么做。 我会很感激你的帮助。 谢谢

【问题讨论】:

【参考方案1】:

我是在我的 Fallback 课程中决定的:

@Component
public class Fallback implements ServiceTwoFeignClient 

    @Autowired
    private ServiceThreeFeignClient serviceThreeFeignClient;

    @Override
    public String getString() 
        return serviceThreeFeignClient.getString();
    


【讨论】:

以上是关于Java Feign 客户端后备 - 无法调用后备的主要内容,如果未能解决你的问题,请参考以下文章

iOS APNS“尽力而为”后备

后备图像和超时 - 外部内容。 Javascript

合约中不存在函数时不调用后备函数

回退如何与 socket.io 一起工作?

Hystrix 后备实施是强制性的吗?

Q3ListView 是不是无法从 Qt 后备存储中注销或代码错误?