SpringCloud从零开始(七)之Hystrix熔断器

前言:

Spring Cloud系列往期点这里
在微服务架构中通常会有多个服务层调用,基础服务的故障可能会导致级联故障,进而造成整个系统不可用的情况,这种现象被称为服务雪崩效应。服务雪崩效应是一种因“服务提供者”的不可用导致“服务消费者”的不可用,并将不可用逐渐放大的过程。
如果下图所示:A作为服务提供者,B为A的服务消费者,C和D是B的服务消费者。A不可用引起了B的不可用,并将不可用像滚雪球一样放大到C和D时,雪崩效应就形成了。
在这里插入图片描述
那么怎么样才能防止,这种级联效应,导致整个服务崩溃呢。那么就需要一根保险丝,在有一个模块出现问题之后,能够采取一定的措施,直接熔断。在Spring Cloud中的这根保险丝就是Hystrix

一、什么是Hystrix

Hystrix 是一个处理分布式系统的延迟和容错的开源库,在分布式系统中 许多依赖的调用不可避免的会出现,调用失败。比如:超时,异常。Hystrix能够保证某个依赖在出现问题的情况下,不会影响整个微服务系统,避免级联故障,提高分布式系统的弹性。

熔断器本身就是一个开关装置, 当某个系统放生调用故障之后,通过熔断器监控的服务(保险丝),向调用的方法返回一个,预期的,可处理的备选相应(fallback),而不是长时间的等待,或者抛出异常。这样就保证了线程不会长时间被占用,避免了资源的占用,也防止了,故障在微服务系统中蔓延,发生雪崩。图片来源官网
在这里插入图片描述
其实熔断器就是一种保护机制,来应对服务调用过程中的超时,异常

二、Hystrix工程搭建

搭建目标
·1、创建工程microservice_product_provider_hystrix8004

创建过程参照microservice_product_provider8001,详情参照分布式项目基础工程搭建
在这里插入图片描述
(2)引入Hystrix的相关依赖

		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
        </dependency>

(3)application.yml的配置如下

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource #使用druid数据源
    driver-class-name: com.mysql.jdbc.Driver
    username: root
    password: root
    url: jdbc:mysql://localhost:3306/springcloud001
  #   数据源其他配置
    initialSize: 5
    minIdle: 5
    maxActive: 20
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
  application:
    name: microservice-provider
server:
  port: 8004
mybatis:        #mybatis基本的配置
  config-location: classpath:mybatis/mybatis-config.xml
  mapper-locations:
    - classpath:mybatis/mapper/ProductMapper.xml

eureka:  #设置eureka注册服务的地址
  client:
    service-url:
        defaultZone:  http://eureka7001:7001/eureka,http://eureka7003:7003/eureka,http://eureka7002:7002/eureka
  instance:
    instance-id: microservice-product-provider-hystrix8004 #配置服务的别名
    prefer-ip-address: true # 注册的时候使用ip注册

其实每个服务的提供者provider,除了端口不同和实例名称不同,其他的配置都是相同的。
** (4)创建熔断服务 **
在原来的ProductController层方法中,创建一个用于发生错误时,快速熔断返回的方法,这样防止由于调用故障,对整个微服务产生影响。并且在目标需要熔断的方法上加上注解配置

    @HystrixCommand(fallbackMethod = "processHystrix")
    @GetMapping("/product/{id}")
    public Product get(@PathVariable Long id){
        Product product = productService.get(id);
        //模拟发生了异常
        if (product==null){
            throw  new RuntimeException();
        }
        return product;
    }
    
    // 熔断服务 快速返回一个预期的 可备选的相应、
    public Product processHystrix(@PathVariable Long id){
        return  new Product().setPid(id).setPName("对不起,该"+id+"在数据库中没有信息");
    }

在上面根据商品id查询商品的get方法上使用了@HystrixCommand(fallbackMethod = "processHystrix")注解,以为着 此方法开启了熔断机制,意味着当,改方法调用不通,比如调用的时候,超时,发生异常,那么熔断机制就会起作用,快速返回一个预期的选项。也就是我们配置的processHystrix方法。

**(5)**在主启动类上开启Hystrix

@SpringBootApplication
@EnableEurekaClient
@EnableHystrix //开启熔断服务
@MapperScan(basePackages = {"com.kuake.dao"}) //扫描mapper接口
public class ProviderHystrix8004Application {
    public static void main(String[] args) {
        SpringApplication.run(ProviderHystrix8004Application.class,args);
    }
}

(6)开始测试
启动

microservice_eureka_7001(注册中心)
microservice_eureka_7002
microservice_eureka_7003
microservice_product_provider_hystrix8004(带有熔断机制的生产者)
microservice_product_consumer80 (消费者)

先访问数据库存在的商品ID http://localhost/consumer/product/1
返回:

{"pid":1,"dbSource":"springcloud001","pname":"舒肤佳"}

现在查询在数据库不存在的id ,用来模拟出异常了。 访问http://localhost/consumer/product/100
返回:

{"pid":100,"dbSource":null,"pname":"对不起,该100在数据库中没有信息"}

服务端并没有因为抛出异常导致服务无法调用,而是返回了可接受的的一个结果,提高的服务的容错性
缺点:
1、@HystrixCommand注解 方法会膨胀,每添加一个注解就会需要一个方法
2、 异常和业务逻辑绑定在一起,耦合度比较高 后期维护比较困难


我们的熔断处理是在服务端进行操作,然而我们也可以将熔断处理的机制提到客户端来,将所有的熔断方法统一提取到api模块中的ProductServiceClient接口中,这样向上提取了一层,并使用一个工厂,统一管理我们的快速回调方法。再讲解这种方法之前,又引出Hystrix解决的另外一种场景,服务降级

什么是服务降级

简单理解服务的降级就是:整体资源不够的情况下,忍痛将某些微服务先关掉,等度过难关,再将服务开启。进行了降级处理之后,让客户端在服务器端不可用的时候,也能收到提示信息,而不挂起 进而耗死服务器。

例如:银行有3个窗口 A B C ,正常情况是 每一个窗口都可以正常服务,但是突然被告知 A窗口要处理更重要的业务,需要增派人手过去,所有采取的策略是 将C窗口的人调去A窗口帮忙。但是还是会有人来C窗口排队,所以要挂一个告示···暂停服务。
为了应对资源不够,暂时关闭一个窗口,但是就算窗口没有人,我们也能得到告示牌上的信息,知道暂停服务,而不是一直等着

我们对之前使用的microservice_product_consumer80_feign进行改造,使用Hystrix让这个客户端有对服务降级的处理。

(1)api模块下创建一个FallBackFactory的接口实现类。ProductClientServiceFallbackFactory.java

public class ProductClientServiceFallbackFactory implements FallbackFactory<ProductClientService> {
    @Override
    public ProductClientService create(Throwable throwable) {


        return new ProductClientService() {
            //可以在反正值里 写一些信息。告诉用户现在不可以访问
            @Override
            public List<Product> list() {
                return null;
            }

            @Override
            public Product get(Long id) {
                return new Product().setPid(id).setPName("对不起 正在降级处理 稍等一段时间再继续访问");
            }

            @Override
            public boolean add(Product product) {
                return false;
            }
        };
    }
}

(2)将api模块的更新同步到本地仓库
`
在这里插入图片描述
(3)在feignservice配置熔断降级服务
添加配置如下:标注工厂

@FeignClient(value = "PROVIDER" ,fallbackFactory=DeptClientServiceFallbackFactory.class)
public interface DeptClientService {

    @GetMapping("/dept/list")
    List<Dept> list();

    @GetMapping("/dept/{id}")
    Dept get(@PathVariable(value = "id") Long id);

    @PostMapping("/dept")
    boolean add(@RequestBody Dept dept);

}

一定要在microservice_product_consumer80_feign中注入这个工厂

    @Bean
    public ProductClientServiceFallbackFactory productClientServiceFallbackFactory (){
        return new ProductClientServiceFallbackFactory();
    }

(4)测试

启动服务
microservice_eureka_7001
microservice_eureka_7002
microservice_eureka_7003
microservice_product_consumer80_feign
microservice_product_provider_hystrix8004

1、正常访问http://localhost/consumer/product/3
返回:

{"pid":3,"dbSource":"springcloud001","pname":"百事可乐"}

模拟降级处理,(上面我们提到,降级就是当资源不够用的时候,忍痛将某些微服务先关掉。)现在我们关掉服务microservice_product_provider_hystrix8004
2、再次访问http://localhost/consumer/product/3
返回:

{"pid":3,"dbSource":null,"pname":"对不起 正在降级处理 稍等一段时间再继续访问"}

返回消息是我们预设的信息,这样虽然服务停止了,但是还能返回有效信息,可以提醒用户,不用一直等待。因为如果返回消息,用户可能会一直频繁操作,导致系统资源占用。这点返回信息,很好的可以降低这种事情的发生。

熔断总结

复杂的分布式系统结构中,会有大量相互依赖的关系,每一个依赖关系在调用的过程中会不可避免的发生,异常,超时。当有大量请求都在等待服务的相应,这些应用程序还可能导致服务之间的延迟增加,从而备份队列,线程和其他系统资源,从而导致整个系统出现更多级联故障。最后甚至会引发雪崩。

熔断机制:当某个服务出现异常,通过@HystrixCommand返回一个可处理的结果,这样服务就不会一直等待有异常的服务。当某个异常条件被触发 ,直接熔断整个服务,而不是一直等待服务超时。(在服务器端)

降级机制: 考虑整体负荷,从而关闭某些服务,但是关闭的服务 也会有请求接着访问,所有要返回一个fallback信息,表明服务不可用,已经被降级了。这样看到消息的用户就不会接着访问,避免了占用资源,资源的挂起和紧张。(客户端)

发布了98 篇原创文章 · 获赞 44 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_43732955/article/details/97656084