武功秘籍之熔断与降级

武功秘籍之熔断与降级

目录

“ 什么是熔断、降级?为什么要做熔断、降级?spring cloud体系下熔断降级是如何设计实现的?”

熔断与降级:
在分布式高并发的环境下,后端每个服务之间的依赖关系非常多,层级非常多,如果一个请求依赖后端的服务A,服务A调用B,服务B调用C,如果这个时候服务B出现异常,就会导致大量的请求超时,在并发量很大的情况下,会瞬间消耗到服务器的CPU与内存资源,导致硬件压力大,从而致使整个服务异常,这个情况又称之为服务雪崩。如下图所示:

举个最近比较火的例子解释一下这个熔断:
3月9日美股开盘暴跌,标普500开盘跌7%触发熔断机制,暂停交易15分钟。
上诉新闻可以看出几个点,第一个是熔断条件:标普500 ,第二个 熔断阈值:跌7% ,第三个是熔断处理机制:暂停交易15分钟。
对于降级呢?很多人不同的理解,这里我个人认为降级可以为熔断之后的一系列处理措施,也就是熔断为触发条件,降级为处理机制。比如说上面美国熔断处理机制,暂停交易15分钟,这个就是服务降级的一个处理方式,下面还有多个服务降级的处理方式:

1、熔断条件触发之后,可以对非核心服务进行限流降级(具体的降级办法,可以通过Hystrix的fallback调整限流接口的阈值)。

2、熔断条件触发之后,可以直接拒绝服务或者关停非核心服务。

3、熔断条件触发之后,可以转发请求到备用服务上。

4、熔断条件触发之后,部分请求可以转发到专门处理异常服务的队列,并根据队列信息进行补偿服务。

本文介绍Netflix开源的Hystrix组件,来具体描述spring cloud体系下,熔断与降级的实现方式。

Hystrix-豪猪

什么是Hystrix:
在分布式环境中,许多服务依赖项中的一些不可避免地会失败。Hystrix是一个库,通过添加延迟容忍和容错逻辑,帮助您控制这些分布式服务之间的交互。Hystrix通过隔离服务之间的访问点、停止服务之间的级联故障以及提供回退选项来实现这一点,所有这些都提高了系统的总体弹性。

官方文档:https://github.com/Netflix/Hystrix/wiki

Hystrix的设计目的:

1、提供对延迟和故障的保护和控制,防止依赖项通过第三方客户端库访问(通常通过网络)。

2、停止复杂分布式系统中的级联故障。

3、故障迅速恢复。

4、在可能的情况下后退并优雅地降级。

5、启用近实时监视、警报和操作控制。

Hystrix是如何设计达成目的:

1、将对外部系统(或“依赖项”)的所有调用包装到HystrixCommand或hystrixobservatablecommand对象中,该对象通常在单独的线程中执行(这是命令模式的示例)。

2、超时调用所需时间超过您定义的阈值。有一个默认值,但对于大多数依赖项,您可以通过“属性”自定义设置这些超时,以便它们略高于每个依赖项的测量99.5%性能。

3、为每个依赖项维护一个小的线程池(或信号量);如果该线程池已满,则为该依赖项指定的请求将立即被拒绝,而不是排队。

4、衡量成功、失败(客户端引发的异常)、超时和线程拒绝。

5、使断路器跳闸,以在一段时间内停止对特定服务的所有请求,手动或自动(如果服务的错误百分比超过阈值)。

6、当请求失败、被拒绝、超时或短路时执行回退逻辑。

7、几乎实时地监视度量和配置更改。

当您使用Hystrix包装每个底层依赖项时,如上图所示的体系结构将更改为类似下图。每个依赖项彼此隔离,在发生延迟时它可以饱和的资源中受到限制,并包含在回退逻辑中,回退逻辑决定当依赖项中发生任何类型的故障时应做出什么响应:

springboot集成Hystrix:

1、引入maven配置,修改pom.xml


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

2、启动文件增加配置

@SpringBootApplication
@EnableHystrix
@EnableEurekaClient
public class KayAdminApplication {
  public static void main(String[] args) {
    SpringApplication.run(KayAdminApplication.class, args);
  }
}

3、修改配置参数 application.yml

#feign相关配置
feign:
  hystrix:
    enabled: true  #开启Feign熔断
#hystrix相关配置
hystrix:
  threadpool:
    default:
      coreSize: 1000 #线程池大小
  command:
    default:
      fallback:
        isolation:
          semaphore:
            maxConcurrentRequests: 1000  #设置调用线程产生的

HystrixCommand.getFallback()方法的允许最大请求数目,如果达到最大并发数目,后续请求将会被拒绝,如果没有实现回退,则抛出异常

  execution:
        isolation:
          thread:
            timeoutInMilliseconds: 6000 #超时时间
        metrics:
            rollingStats:
                timeInMilliseconds: 2000 #默认值10000,滚动窗口的时间范围
        circuitBreaker:
            requestVolumeThreshold: 10000 #默认值20,设置在一个滚动窗口中,打开断路器的最少请求数
            errorThresholdPercentage: 80  #出错百分比阈值,当达到此阈值后,开始短路
            sleepWindowInMilliseconds: 1000 #短路多久以后开始尝试是否恢复,默认值 5000,休眠期的持续时间

3、结合feigin使用


@FeignClient(value = "service-uid", fallbackFactory = ServiceUidHystric.class)
@Service
public interface ServiceUidFeign {

    @RequestMapping(value = "/service/get/ids", method = RequestMethod.POST)
    Result getNextIds(@RequestBody GenerateIdVO generateIdVO);

    @RequestMapping(value = "/service/check/ids", method = RequestMethod.POST)
    Result checkIds(@RequestBody GenerateIdVO generateIdVO);

}

4、开发fallback模块

public interface ServicetUidFallBackFactory extends ServiceUidFeign {

}

@Component
public class ServiceUidHystric implements FallbackFactory<ServiceUidFeign> {
    private static final Logger logger = LoggerFactory.getLogger(ServiceUidHystric.class);

    @Override
    public ServiceUidFeign create(Throwable throwable) {
        return new ServicetUidFallBackFactory(){
            @Override
            public Result getNextIds(@RequestBody GenerateIdVO generateIdVO){
                //这里主要为降级的具体处理逻辑,demo只记录异常信息,并返回异常信息
                logger.error("http://service-uid/service/get/ids:request fail:{}",
                    JSON.toJSONString(generateIdVO),throwable.getMessage());
                return ResultUtils.internalError("Service fuses.");
            }

            @Override
            public Result checkIds(@RequestBody GenerateIdVO generateIdVO){
                logger.error("http://service-uid/service/check/ids:request fail:{}",
                    JSON.toJSONString(generateIdVO),throwable.getMessage());
                return ResultUtils.internalError("Service fuses.");
            }
        };
    }
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/zk18286047195/article/details/106052510