Hystrix入门(含服务降级出现的No fallbackFactory instance of type class)

SpringCloud入门案例-GitHub(含本文代码)
断路器的引入就是SpringCloud对分布式的不信任。现实中确实是这样的,分布式系统是不完全可靠的,总会出现服务断开、延迟等情况。以下两张截图均来自官方网站
在这里插入图片描述
在这里插入图片描述
使用spring-cloud-starter-hystrix入门。
涉及模块如下图
在这里插入图片描述
首先一定要弄清楚Hystrix作用于服务提供者。
所以有了第一个版本:
只需要在服务提供者的Controller中使用@HystrixCommand就可以实现服务熔断,防止服务雪崩。

@RestController
public class DeptController {

    @Autowired
    private DeptServiceImpl deptService;

    @RequestMapping(value = "/dept/get/{id}", method = RequestMethod.GET)
    //一旦调用服务方法失败并抛出异常信息后,会自动调用fallbackMethod指定的方法
    //这里的代码有很大的两个问题:1.每个方法都跟随一个fallbackMethod导致这个类方法膨胀;2.违背了Spring切面编程的思想,业务处理不纯粹了
    //在api项目中使用的feign使用了接口编程的方式,利用AOP思想将hystrix熔断机制提取出去统一到了接口级别
    @HystrixCommand(fallbackMethod = "processHystrix_Get")
    public Dept get(@PathVariable("id") Long id){
        Dept dept = this.deptService.get(id);
        if (null == dept){
            throw new RuntimeException("该ID:" + id + "没有对应的数据");
        }
        return dept;
    }

    //在api项目中已经将熔断提出到了接口上,这里就不需要这段代码,使此业务类能够纯粹的处理业务
    public Dept processHystrix_Get(@PathVariable("id") Long id){
        return new Dept().setDeptno(id).setDname("该ID" + id + "没有对应的数据").setDb_source("no this DataBase in Mysql");
    }
}

在启动类上必须加@EnableCircuitBreaker注解

@SpringBootApplication
@EnableEurekaClient//本服务会自动注册进Eureka注册中心中
@EnableDiscoveryClient
@EnableCircuitBreaker//开启对熔断器的支持
public class DeptServiceMainApplicationHystrix8001 {
    public static void main(String[] args) {
        SpringApplication.run(DeptServiceMainApplicationHystrix8001.class, args);
    }
}

上面的代码结果是查询数据中存在数据的时候会显示正常结果,但是一旦查询不到不会立马报错,而是立马返回我们期望返回的数据
在这里插入图片描述
在这里插入图片描述
如上面的代码截图框起来的描述,我们便发现了一个问题,这个服务类不”纯粹“了,违背了Spring的切面编程的思想,导致服务类变得很沉重。
所以我们尊重AOP的思想,必须将非业务代码移除出去。
在api公共服务项目中创建一个专门用于写Hystrix的类,专门实现服务熔断以及降级。
这里就说说何为降级,它与熔断是有何区别?熔断是服务出现异常,直接返回期望数据;而降级呢,是服务是正常的,只是此服务在集群中属于优先级较低的服务,当集群资源出现紧张的情况,此服务会暂时关闭,将资源留给更需要资源的服务(舍己为人)。

  • 公共服务项目
@Component   //千万不要忘记加Component注解
public class DeptClientServiceFallbackFactory implements FallbackFactory<DeptClientService> {
    @Override
    public DeptClientService create(Throwable throwable) {
        return new DeptClientService() {
            @Override
            public boolean add(Dept dept) {
                return false;
            }

            @Override
            public Dept get(Long id) {
                return new Dept().setDeptno(id).setDname("该ID:" + id + "没有对应的数据,Consumer客户端提供的降级信息,此服务Provider已经停止" +
                        "关闭").setDb_source("no this DataBase in the Mysql");
            }

            @Override
            public List<Dept> list() {
                return null;
            }
        };
    }
}

DeptClientService

//这里将hystrix服务提取到了接口层面
@FeignClient(value = "MICROSERVICECLOUD-PROVIDER-DEPT", fallbackFactory = DeptClientServiceFallbackFactory.class)
//@FeignClient(value = "MICROSERVICECLOUD-PROVIDER-DEPT")
public interface DeptClientService {

//    @GetMapping("/consumer/dept/add")这里写客户端的访问地址是错误的,因为我们是给服务端做熔断器,所以使用服务端的RequestMapping,
    //否则客户端所有请求都会执行服务降级,导致服务不可用
    @RequestMapping(value = "/dept/add", method = RequestMethod.GET)
    public boolean add(Dept dept);

//    @GetMapping("/dept/get/{id}")
    @RequestMapping(value = "/dept/get/{id}", method = RequestMethod.GET)
    public Dept get(@PathVariable("id") Long id);

    @SuppressWarnings("unchecked")
//    @GetMapping("/dept/list")
    @RequestMapping(value = "/dept/list", method = RequestMethod.GET)
    public List<Dept> list();
}

此时服务提供者中的代码就简化了

  • 服务提供者
@RestController
public class DeptController {

    @Autowired
    private DeptServiceImpl deptService;

    @RequestMapping(value = "/dept/get/{id}", method = RequestMethod.GET)
    
    public Dept get(@PathVariable("id") Long id){
        Dept dept = this.deptService.get(id);
        if (null == dept){
            throw new RuntimeException("该ID:" + id + "没有对应的数据");
        }
        return dept;
    }
}

服务提供者就很”纯粹“了。

  • 服务提供者
    由于配合使用了feign,所以服务消费者也有所改动。主要体现在它需要知道配置熔断器的类
@RestController
public class DeptController_Consumer_Feign {
	//在之前使用了feign,所以使用了DeptClientService作为代理处理请求
    @Autowired
    private DeptClientService service;

    //方便测试都使用的是HTTP的Get方法
    //注意:这里不能使用GetMapping,会报404错误的
//    @GetMapping("/consumer/dept/add")
    @RequestMapping(value = "/consumer/dept/add", method = RequestMethod.GET)
    public boolean add(Dept dept){
        return service.add(dept);
    }

//    @GetMapping("/consumer/dept/get/{id}")
    @RequestMapping(value = "/consumer/dept/get/{id}", method = RequestMethod.GET)
    public Dept get(@PathVariable("id") Long id){
        return service.get(id);
    }

    @SuppressWarnings("unchecked")
    @RequestMapping(value = "/consumer/dept/list", method = RequestMethod.GET)
    public List<Dept> list(){
        return service.list();
    }
}

启动类:

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients(basePackages = {"com.ittx.service.dept.feign"})
//这个注解非常重要
@ComponentScan({"com.ittx.springcloud","com.ittx.service.dept.hystrix"})
public class DeptConsumerFeignMainApplication {
    public static void main(String[] args) {
        SpringApplication.run(DeptConsumerFeignMainApplication.class, args);
    }
}

这样既实现了服务熔断和降级
服务熔断与之前效果一样。
模拟服务降级,将服务提供者关闭。
在这里插入图片描述
服务就算关闭了,此时也没有报错,而是返回我们期望的数据。
在这里插入图片描述
以上就是简单的hystrix入门案例。
代码不全面,需要全部代码后期会将GitHub链接奉上。


好了,案例总结完毕,就要总结启动服务消费者的时候报No fallbackFactory instance of type class错误的解决办法。 首先要明确这个是没有fallbackFactory实例,我们的项目中的DeptClientServiceFallbackFactory就是实现了FallbackFactory接口,也就是说这个类没有被实例化,没有进入IOC容器。
  1. 检查DeptClientServiceFallbackFactory类上有没有@Component注解,这个一定不要忘记
  2. 由于服务消费者使用的DeptClientService作为代理访问注册中心的服务,所以一定要检查FallbackFactory传入的泛型是否正确
    在这里插入图片描述
  3. 在DeptClientService类上的@FeignClient注解中fallbackFactory属性值写正确否
    在这里插入图片描述
  4. 在服务消费者的启动类中是否将FallbackFactory实现类扫描进IOC容器
    在这里插入图片描述
    这里就要说一下@ComponentScan和@SpringBootApplication一起使用的时候,@SpringBootApplication中的扫描注解将失效,所以在@Component注解中需要将本项目需要扫描和引入的其他项目需要扫描的包都要写进去才行。
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
这个错误是因为无法找到名为 "feign/hystrix/FallbackFactory.class" 的类路径资源,所以会报错。 这可能是因为您的项目缺少了相应的依赖或配置文件。根据引用的描述,您提到的 spring.xml 配置文件可能位于 resource 目录下,但您的项目中可能没有正确加载该资源。 根据引用的描述,您可能需要导入 Feign 相关的依赖包。确保您的项目中已经添加了以下依赖: ``` <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> ``` 请仔细检查您的项目配置和依赖是否正确,并确保所需的类路径资源存在于正确的位置。如果问题仍然存在,请检查文件路径或联系相关开发人员进行进一步的调试和解决。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [解决报错class path resource [spring.xml] cannot be opened because it does not exist......](https://blog.csdn.net/qq_42490860/article/details/129534982)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [SpringCloud启动Provider微服务时出现java.io.FileNotFoundException异常](https://blog.csdn.net/qq_46010154/article/details/111250624)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值