• Hystrix 容错处理


    雪崩效应

    在一个微服务系统之中,各个服务之间存在相互依赖,如A-->B-->C,
    一旦C由于某种原因无法使用,则会导致A、B都无法使用
    超时线程会一直等待下去,处于阻塞状态。一旦这种请求多了,则系统就崩了

    在分布式系统中,如果一个服务长期被占用,则可以通过断路器直接返回错误信息,
    释放资源,避免了错误在分布式系统中的蔓延。

    术语:基础服务故障导致级联故障的现象称为雪崩效应。

    容错的基本思想

    • 网络请求超时设置

    每次请求,其返回必须是明确的。
    要么返回正常数据,要么在指定时长后返回异常数据。
    不应该陷入无限制的等待中

    • 断路器模式

    断路器可以理解为对容易导致错误的操作的代理。
    这种代理能够统计一段时间内调用失败的次数,并决定是正常请求还是直接返回。

    当某个服务的请求失败率达到阀值后,应该开启断路器,使该服务不再被调用。

    断路器启动后,过会儿允许调用被关闭的服务,检测一下是否已经恢复正常

    什么是Hystrix

    Hystrix是一个实现了超时机制和断路器模式的工具类库。
    用于隔离远程访问系统、服务或者第三方库,防止级联失败。
    从而提升系统的可用性与容错性。

    通过以下几点实现延迟和容错

    • 包裹请求

    调用依赖的服务,这个过程在独立线程中执行

    • 跳闸机制

    当服务错误率到达设定的阀值,Hystrix可以自动或者手动跳闸。
    停止该服务一段时间。

    • 资源隔离

    Hystrix为每个依赖的服务都维护了一个小型的线程池(或信号量)
    如果该线程池已满,则发往该服务的请求立马被拒绝,而不是排队等候。加速失败判定。

    • 监控
    • 回退机制

    请求失败后,执行回退逻辑
    一般是回滚一些操作或执行降级服务

    • 自我修复

    断路器打开一段时间后检查服务是否可用
    如果服务可用使用了,则继续提供服务

    简单使用

    消费端使用Hystrix

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

    注解开启

    在启动类上使用注解开启

    @EnableCircuitBreaker//注解开启断路器功能
    

    此时我们的启动类上就有了3个注解

    @EnableDiscoveryClient//注册为Eureka客户端
    @EnableCircuitBreaker//注解开启断路器功能
    @SpringBootApplication
    

    这三个注解可以使用一个注解代替

    @SpringCloudApplication
    

    是等效的,因为@SpringCloudApplication的源码如下

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @SpringBootApplication
    @EnableDiscoveryClient
    @EnableCircuitBreaker
    public @interface SpringCloudApplication {
    }
    

    可见,Spring Cloud官方认为,对于一个Spring Cloud应用,
    是应该包含服务发现与断路器的

    改造消费方法

    新增一个service层代码

    package org.zln.spb.service;
    
    import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.web.client.RestTemplate;
    
    /**
     * Created by nbcoolkid on 2017-10-21.
     */
    @Service
    public class HelloService {
    
        @Autowired
        private RestTemplate restTemplate;
    
        @HystrixCommand(fallbackMethod = "helloFallBack")
        public String helloService(String name) {
            return restTemplate.getForObject("http://HELLO-SERVICE/hello?name={1}", String.class, name);
        }
    
        public String helloFallBack(String name) {
            return "error" + name;
        }
    
    }
    

    @HystrixCommand(fallbackMethod = "helloFallBack")
    当调用失败的时候,就去调用helloFallBack方法
    那么什么是调用失败呢?链路断了、超时等。
    默认Hystrix的超时时间为2000ms,只要超过2秒没有响应,就会认为本次调用失败

    值得一提的是这个错误回调方法的参数与返回类型,需要与helloService保持一致

    这里,我们的fallbackMethod是一个异常提示信息,
    另一种常见的情况是调用方法A失败后,去调用方法B
    方法B失败后,去调用方法C,也就是helloFallBack上也是可以使用@HystrixCommand的

    形成一个异常调用的执行链,形成服务降级链条

    @HystrixCommand 详细配置

    在上例中,我们只是使用fallbackMethod属性配置了调用异常后的回调方法。
    其实还有很多更加强大的配置项,下面我们详细讲讲。

    @HystrixCommand(fallbackMethod = "helloFallBack", commandProperties = {
    				@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000"),
    				@HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "10000")
    }, threadPoolProperties = {
    				@HystrixProperty(name = "coreSize", value = "1"),
    				@HystrixProperty(name = "maxQueueSize", value = "10")
    })
    public String helloService(String name) {
    		return restTemplate.getForObject("http://demo02-provider/test/t1?name={name}", String.class, name);
    }
    
    

    @HystrixCommand除了可以配置在Service层,
    其实更多的是配置在Controller层。
    对于一笔服务调用来说,Controller才是他的入口

    更详细的配置信息:https://github.com/Netflix/Hystrix/wiki/Configuration

    Hystrix线程隔离策略与传播上下文

    Hystrix的隔离策略有两种

    • 线程隔离(默认)

    HystrixCommand将会在单独的线程上执行,并发请求受线程池中的线程数量的限制。

    • 信号量隔离

    HystrixCommand将会在调用线程执行,开销相对较小。
    并发请求受到信号量个数的限制。

    之所以默认使用线程隔离,是因为这种方式有一个除了网络超时以外的额外保护层。
    一般只有当负载非常高(每个实例每秒数百次)才需要使用信号量隔离。
    信号量隔离一般仅适用于非网络调用的隔离。
    使用execution.isolation.strategy属性指定隔离策略

    @HystrixCommand(fallbackMethod = "helloFallBack", commandProperties = {
    				@HystrixProperty(name = "execution.isolation.strategy", value = "SEMAPHORE")
    }, threadPoolProperties = {
    				@HystrixProperty(name = "coreSize", value = "1"),
    				@HystrixProperty(name = "maxQueueSize", value = "10")
    })
    
    

    SEMAPHORE表示信号量,THREAD表示线程。
    当然,如果采用线程隔离的话,不配置就行了。

    Hystrix监控

    状态监控

    Hystrix断路器的状态也会暴露在Actuator的/health端点中,所以我们引入Actuator模块。

    注意:

    
    management:
      security:
        enabled: false
    

    配置上述,用于在/health端点中查看到更多信息。

    小实验:

    在消费端引入Hystrix作为断路器,引入Actuator作为监控组件。

    • 正常访问

    对其中的服务进行正常访问

    • 查看/health

    访问消费端的 http://localhost:10005/health,显示服务端正常

    • 停止服务提供者

    因为服务提供者停止了,消费者访问肯定会失败。
    所以这个时候进行请求,会返回降级处理的结果。

    • 继续访问/health

    这个时候虽然服务提供者已经挂了,
    但是我们访问消费者的/health端点,仍旧任务服务处于up状态。

    那因为失败率还没到达阀值。(默认5秒内20次失败)

    • 触发阀值

    通过多个标签页,不停的访问消费者。达到触发断路器的条件。
    此时再访问/health端点,就能够发现Hystrix的status处于CIRCUIT_OPEN状态了。

  • 相关阅读:
    web服务器12 中间件函数
    web11 路由
    web服务器15 jsonp格式接口
    web服务器14 cors跨域资源共享 报错及解决方案
    小程序弹窗(模态框)遮罩层 弹窗右上角按钮关闭
    数据库1 mysq数据库的安装全套
    MySQL数据库3 的 where语句 and 和 or运算符
    MySQL数据库2 增删改查
    MySQL分组排序取每组第一条
    IDEA频繁闪退解决
  • 原文地址:https://www.cnblogs.com/sherrykid/p/7775028.html
Copyright © 2020-2023  润新知