SpringCloud Alibaba微服务实战二十 - 集成Feign的降级熔断

简介: SpringCloud Alibaba微服务实战二十 - 集成Feign的降级熔断

在之前的项目中我们已经实现了使用Feign调用远程接口,本章内容主要是借助sentinel实现Feign接口熔断器功能。


概述


首先我们看看不使用熔断器的情况下调用一个没有启动的服务会出现什么效果,然后再来看看使用sentinel熔断器后的效果。

如上,我们使用order-service中 FeignController调用account-service中的接口,在没启用熔断器的情况下,接口会抛出500异常。


实现


使用sentinel实现熔断器很简单,简单几步即可。

  1. 定义fallback类,当熔断时返回默认数据
package com.javadaily.feign.fallback;
@Slf4j
public class AccountFeignFallback implements AccountFeign {
    @Setter
    private Throwable cause;
    @Override
    public ResultData<String> insert(AccountDTO accountDTO) {
        return ResultData.fail("接口熔断");
    }
    @Override
    public ResultData<String> delete(String accountCode) {
        return ResultData.fail("接口熔断");
    }
    @Override
    public ResultData<String> update(AccountDTO accountDTO) {
        return ResultData.fail("接口熔断");
    }
    @Override
    public ResultData<AccountDTO> getByCode(String accountCode) {
        log.error("查询失败,接口异常" ,cause);
        AccountDTO account = new AccountDTO();
        account.setAccountCode("000");
        account.setAccountName("测试Feign");
        return ResultData.success(account);
    }
    @Override
    public ResultData<String> reduce(String accountCode, BigDecimal amount) {
        return ResultData.fail("接口熔断");
    }
}
  1. 编写FallbackFactory
@Component
public class AccountFeignFallbackFactory implements FallbackFactory<AccountFeign> {
    @Override
    public AccountFeign create(Throwable throwable) {
        AccountFeignFallback accountFeignFallback = new AccountFeignFallback();
        accountFeignFallback.setCause(throwable);
        return accountFeignFallback;
    }
}
  1. 给feign接口指定熔断工厂
@FeignClient(name = "account-service",fallbackFactory = AccountFeignFallbackFactory.class)
public interface AccountFeign {
    ...
}
  1. 在消费中配置文件中开启熔断
feign:
  sentinel:
    enabled: true

经过以上四步我们就可以实现了接口的熔断,接下来重新启动order-service验证结果。系统居然无法正常启动!!!


堆栈信息如下:

2020-10-23 15:22:14,286 ERROR SpringApplication:826 - Application run failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'feignController': Unsatisfied dependency expressed through field 'accountFeign'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.javadaily.feign.account.AccountFeign': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalStateException: No fallbackFactory instance of type class com.javadaily.feign.factory.AccountFeignFallbackFactory found for feign client account-service
 at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:643) ~[spring-beans-5.2.4.RELEASE.jar:5.2.4.RELEASE]
 at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:130) ~[spring-beans-5.2.4.RELEASE.jar:5.2.4.RELEASE]


问题解决

俗话说「出现问题不可怕,可怕的是我们害怕出现问题」,看上面的启动日志应该是无法找到 AccountFeignFallbackFactory,接下来我们看一下FeignClient的源码:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FeignClient {
 ...省略部分代码,保留关键代码...
 /**
  * Fallback class for the specified Feign client interface. The fallback class must
  * implement the interface annotated by this annotation and be a valid spring bean.
  * @return fallback class for the specified Feign client interface
  */
 Class<?> fallback() default void.class;
 ...省略部分代码,保留关键代码...
}

注意看注释部分,说的是Feign的降级类必须实现该Feign接口并且必须是一个Spring Bean。

出现错误的原因应该是「降级类没有被注册成Spring  Bean。」

大家都知道,在SpringBoot启动的时候会默认扫描主启动类所在的包以及子包进行Bean实例化。

项目中的order-service的主启动类位于 com.javadaily.order,那么order-service项目启动时只会扫描到 com.javadaily.order以及 com.javadaily.order的子包,而AccountFeignClient的降级类 AccountFeignFallback的包路径为 com.javadaily.feign.fallback ,这样就无法被Spring实例化,最终导致项目启动失败。

既然定位到了问题原因那就很好解决了,只要在启动类上配置Feign降级类的包路径即可。

@SpringBootApplication(scanBasePackages = {"com.javadaily.feign"})

加上这个配置后系统能正常启动,但是调用接口又返回如下的错误:

{
  "timestamp": "2020-10-27T03:30:44.664+0000",
  "status": 401,
  "error": "Unauthorized",
  "message": "Unauthorized",
  "path": "/order/getAccount/jianzh5"
}

出现这个问题的原因是我们通过scanBasePackages配置Feign降级类的路径后自身的Bean无法实例化,所以我们还需要配置上我们自己项目的扫描路径,即:

@SpringBootApplication(scanBasePackages = {"com.javadaily.feign","com.javadaily.order"})

至此所有问题都解决,我们再次访问接口,当系统故障时返回我们默认结果。


小结


本章内容我们通过给Feign的接口加上熔断器,当实例故障时系统会返回默认数据。这样就不会出现当某一个服务不可用时导致他的消费者长时间等待,线程池耗尽,进而影响到其他服务的线程调用,这也是常说的 "雪崩效应"。

当然了实现过程中出现了一点小挫折,总结下来就是「如果各位的Feign客户端是由消费者自己编写,位于消费者自己模块不会出现这个问题。如果是由生产者编写并提供则需要注意Spring Bean实例化的扫描路径,如果无法扫描实例化熔断类,只需要在启动类上通过 scanBasePackages扫描到对应的路径即可」


如果本文对你有帮助,别忘记来个三连:点赞,转发,评论咱们下期见!

收藏 等于白嫖点赞 才是真情!

目录
相关文章
|
15天前
|
运维 NoSQL Java
后端架构演进:微服务架构的优缺点与实战案例分析
【10月更文挑战第28天】本文探讨了微服务架构与单体架构的优缺点,并通过实战案例分析了微服务架构在实际应用中的表现。微服务架构具有高内聚、低耦合、独立部署等优势,但也面临分布式系统的复杂性和较高的运维成本。通过某电商平台的实际案例,展示了微服务架构在提升系统性能和团队协作效率方面的显著效果,同时也指出了其带来的挑战。
55 4
|
1月前
|
Dubbo Java 应用服务中间件
Dubbo学习圣经:从入门到精通 Dubbo3.0 + SpringCloud Alibaba 微服务基础框架
尼恩团队的15大技术圣经,旨在帮助开发者系统化、体系化地掌握核心技术,提升技术实力,从而在面试和工作中脱颖而出。本文介绍了如何使用Dubbo3.0与Spring Cloud Gateway进行整合,解决传统Dubbo架构缺乏HTTP入口的问题,实现高性能的微服务网关。
|
28天前
|
JSON Java 数据格式
【微服务】SpringCloud之Feign远程调用
本文介绍了使用Feign作为HTTP客户端替代RestTemplate进行远程调用的优势及具体使用方法。Feign通过声明式接口简化了HTTP请求的发送,提高了代码的可读性和维护性。文章详细描述了Feign的搭建步骤,包括引入依赖、添加注解、编写FeignClient接口和调用代码,并提供了自定义配置的示例,如修改日志级别等。
75 1
|
2月前
|
负载均衡 Java Nacos
SpringCloud基础2——Nacos配置、Feign、Gateway
nacos配置管理、Feign远程调用、Gateway服务网关
SpringCloud基础2——Nacos配置、Feign、Gateway
|
2月前
|
前端开发 API 微服务
SpringCloud微服务之间使用Feign调用不通情况举例
SpringCloud微服务之间使用Feign调用不通情况举例
497 2
|
2月前
|
运维 持续交付 API
深入理解并实践微服务架构:从理论到实战
深入理解并实践微服务架构:从理论到实战
133 3
|
2月前
|
自然语言处理 Java 网络架构
解锁跨平台微服务新纪元:Micronaut与Kotlin联袂打造的多语言兼容服务——代码、教程、实战一次打包奉送!
【9月更文挑战第6天】Micronaut是一款轻量级、高性能的Java框架,适用于微服务开发。它支持Java、Groovy和Kotlin等多种语言,提供灵活的多语言开发环境。本文通过创建一个简单的多语言兼容服务,展示如何使用Micronaut及其注解驱动特性实现REST接口,并引入国际化支持。无论是个人项目还是企业应用,Micronaut都能提供高效、一致的开发体验,成为跨平台开发的利器。通过简单的配置和代码编写,即可实现多语言支持,展现其强大的跨平台优势。
52 3
|
2月前
|
运维 监控 持续交付
深入浅出:微服务架构的设计与实战
微服务,一个在软件开发领域如雷贯耳的名词,它代表着一种现代软件架构的风格。本文将通过浅显易懂的语言,带领读者从零开始了解微服务的概念、设计原则及其在实际项目中的运用。我们将一起探讨如何将一个庞大的单体应用拆分为灵活、独立、可扩展的微服务,并分享一些实践中的经验和技巧。无论你是初学者还是有一定经验的开发者,这篇文章都将为你提供新的视角和深入的理解。
80 3
|
2月前
|
Java API 开发者
【已解决】Spring Cloud Feign 上传文件,提示:the request was rejected because no multipart boundary was found的问题
【已解决】Spring Cloud Feign 上传文件,提示:the request was rejected because no multipart boundary was found的问题
398 0
|
4月前
|
监控 druid Java
spring boot 集成配置阿里 Druid监控配置
spring boot 集成配置阿里 Druid监控配置
289 6