当前位置:   article > 正文

SpringBoot 服务熔断降级之-Hystrix_服务熔断和服务降级 hystix和feigin 负实现服务降级

服务熔断和服务降级 hystix和feigin 负实现服务降级

SpringBoot 服务熔断降级之-Hystrix

熔断属性配置类:HystrixCommandProperties

protected HystrixCommandProperties(HystrixCommandKey key, HystrixCommandProperties.Setter builder, 
                                   String propertyPrefix) {
        this.key = key;
        this.circuitBreakerEnabled = getProperty(propertyPrefix, key, "circuitBreaker.enabled", builder.getCircuitBreakerEnabled(), default_circuitBreakerEnabled);
        this.circuitBreakerRequestVolumeThreshold = getProperty(propertyPrefix, key, "circuitBreaker.requestVolumeThreshold", builder.getCircuitBreakerRequestVolumeThreshold(), default_circuitBreakerRequestVolumeThreshold);
        this.circuitBreakerSleepWindowInMilliseconds = getProperty(propertyPrefix, key, "circuitBreaker.sleepWindowInMilliseconds", builder.getCircuitBreakerSleepWindowInMilliseconds(), default_circuitBreakerSleepWindowInMilliseconds);
        this.circuitBreakerErrorThresholdPercentage = getProperty(propertyPrefix, key, "circuitBreaker.errorThresholdPercentage", builder.getCircuitBreakerErrorThresholdPercentage(), default_circuitBreakerErrorThresholdPercentage);
        this.circuitBreakerForceOpen = getProperty(propertyPrefix, key, "circuitBreaker.forceOpen", builder.getCircuitBreakerForceOpen(), default_circuitBreakerForceOpen);
        this.circuitBreakerForceClosed = getProperty(propertyPrefix, key, "circuitBreaker.forceClosed", builder.getCircuitBreakerForceClosed(), default_circuitBreakerForceClosed);
        this.executionIsolationStrategy = getProperty(propertyPrefix, key, "execution.isolation.strategy", builder.getExecutionIsolationStrategy(), default_executionIsolationStrategy);
        this.executionTimeoutInMilliseconds = getProperty(propertyPrefix, key, "execution.isolation.thread.timeoutInMilliseconds", builder.getExecutionIsolationThreadTimeoutInMilliseconds(), default_executionTimeoutInMilliseconds);
        this.executionTimeoutEnabled = getProperty(propertyPrefix, key, "execution.timeout.enabled", builder.getExecutionTimeoutEnabled(), default_executionTimeoutEnabled);
        this.executionIsolationThreadInterruptOnTimeout = getProperty(propertyPrefix, key, "execution.isolation.thread.interruptOnTimeout", builder.getExecutionIsolationThreadInterruptOnTimeout(), default_executionIsolationThreadInterruptOnTimeout);
        this.executionIsolationThreadInterruptOnFutureCancel = getProperty(propertyPrefix, key, "execution.isolation.thread.interruptOnFutureCancel", builder.getExecutionIsolationThreadInterruptOnFutureCancel(), default_executionIsolationThreadInterruptOnFutureCancel);
        this.executionIsolationSemaphoreMaxConcurrentRequests = getProperty(propertyPrefix, key, "execution.isolation.semaphore.maxConcurrentRequests", builder.getExecutionIsolationSemaphoreMaxConcurrentRequests(), default_executionIsolationSemaphoreMaxConcurrentRequests);
        this.fallbackIsolationSemaphoreMaxConcurrentRequests = getProperty(propertyPrefix, key, "fallback.isolation.semaphore.maxConcurrentRequests", builder.getFallbackIsolationSemaphoreMaxConcurrentRequests(), default_fallbackIsolationSemaphoreMaxConcurrentRequests);
        this.fallbackEnabled = getProperty(propertyPrefix, key, "fallback.enabled", builder.getFallbackEnabled(), default_fallbackEnabled);
        this.metricsRollingStatisticalWindowInMilliseconds = getProperty(propertyPrefix, key, "metrics.rollingStats.timeInMilliseconds", builder.getMetricsRollingStatisticalWindowInMilliseconds(), default_metricsRollingStatisticalWindow);
        this.metricsRollingStatisticalWindowBuckets = getProperty(propertyPrefix, key, "metrics.rollingStats.numBuckets", builder.getMetricsRollingStatisticalWindowBuckets(), default_metricsRollingStatisticalWindowBuckets);
        this.metricsRollingPercentileEnabled = getProperty(propertyPrefix, key, "metrics.rollingPercentile.enabled", builder.getMetricsRollingPercentileEnabled(), default_metricsRollingPercentileEnabled);
        this.metricsRollingPercentileWindowInMilliseconds = getProperty(propertyPrefix, key, "metrics.rollingPercentile.timeInMilliseconds", builder.getMetricsRollingPercentileWindowInMilliseconds(), default_metricsRollingPercentileWindow);
        this.metricsRollingPercentileWindowBuckets = getProperty(propertyPrefix, key, "metrics.rollingPercentile.numBuckets", builder.getMetricsRollingPercentileWindowBuckets(), default_metricsRollingPercentileWindowBuckets);
        this.metricsRollingPercentileBucketSize = getProperty(propertyPrefix, key, "metrics.rollingPercentile.bucketSize", builder.getMetricsRollingPercentileBucketSize(), default_metricsRollingPercentileBucketSize);
        this.metricsHealthSnapshotIntervalInMilliseconds = getProperty(propertyPrefix, key, "metrics.healthSnapshot.intervalInMilliseconds", builder.getMetricsHealthSnapshotIntervalInMilliseconds(), default_metricsHealthSnapshotIntervalInMilliseconds);
        this.requestCacheEnabled = getProperty(propertyPrefix, key, "requestCache.enabled", builder.getRequestCacheEnabled(), default_requestCacheEnabled);
        this.requestLogEnabled = getProperty(propertyPrefix, key, "requestLog.enabled", builder.getRequestLogEnabled(), default_requestLogEnabled);
        this.executionIsolationThreadPoolKeyOverride = HystrixPropertiesChainedProperty.forString().add(propertyPrefix + ".command." + key.name() + ".threadPoolKeyOverride", (Object)null).build();
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
三、线程隔离和服务降级
  1. 线程隔离

    Hystrix为每个依赖服务调用分配一个小的线程池,如果线程池已满调用将被立即拒绝,默认不采用排队,加速失败判定时间。
    用户的请求将不再直接访问服务,而是通过线程池中的空闲线程来访问服务,如果线程池已满,或者请求超时,则会进行降级处理。

  2. 服务降级

    用户的请求故障时,不会被阻塞,更不会无休止的等待或者看到系统崩溃,至少可以看到一个执行结果(例如返回友好的提示信息) 即:及时返回服务调用失败的结果,让线程不因为等待服务而阻塞。
    服务降级虽然会导致请求失败,但是不会导致阻塞,而且最多会影响这个依赖服务对应的线程池中的资源,对其它服务没有响应。可以优先保证核心服务。
    触发Hystrix服务降级的情况:线程池已满、请求超时。

四、消费端系统实现服务降级

服务端系统只是一个简单的查询功能:

  1. 引入依赖
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
  • 1
  • 2
  • 3
  • 4
  1. 开启熔断
    在启动类 ConsumerApplication 上添加注解@EnableCircuitBreaker

    @SpringBootApplication
    //eureka注册的注解
    @EnableDiscoveryClient
    @EnableCircuitBreaker
    public class ConsumerApplication {
    // ...
    }
    
    //特别的:注解@SpringCloudApplication等效于@SpringBootApplication、@EnableDiscoveryClient和@EnableCircuitBreaker三个注解
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    1. 编写降级逻辑

      当目标服务的调用出现故障,我们希望快速失败,给用户一个友好提示。因此需要提前编写好失败时的降级处理逻辑,可使用@HystrixCommand和@DefaultProperties来完成。
      因为熔断的降级逻辑方法必须跟正常逻辑方法保证:相同的参数列表和返回值声明。
      @HystrixCommand,可单独设置某一个方法的降级处理逻辑。

      @RestController
      @RequestMapping("/consumer")
      //日志注解
      @Slf4j
      public class ConsumerController {
      	@Autowired
      	private RestTemplate restTemplate;
      	@Autowired
      	private DiscoveryClient discoveryClient;
      	@GetMapping("{id}")
      	//用来声明一个降级逻辑的方法
      	@HystrixCommand(fallbackMethod = "queryByIdFallback")
      	public String queryById(@PathVariable Long id) {
      		String url = "http://user-service/user/" + id;
      		return restTemplate.getForObject(url, String.class);
      	}
      public String queryByIdFallback(Long id) {
      	log.error("查询用户信息失败。id:{}", id);
      	return "对不起,网络太拥挤了!";
      	}
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22

      @DefaultProperties,默认fallback,可设置统一的降级服务逻辑。

      @RestController
      @RequestMapping("/consumer")
      @Slf4j
      //默认降级逻辑的方法
      @DefaultProperties(defaultFallback = "defaultFallback")
      public class ConsumerController {
      	@Autowired
      	private RestTemplate restTemplate;
      	@Autowired
      	private DiscoveryClient discoveryClient;
      	@GetMapping("{id}")
      	//这个也要写
      	@HystrixCommand
      	public String queryById(@PathVariable Long id) {
      		String url = "http://user-service/user/" + id;
      		return restTemplate.getForObject(url, String.class);
      	}
      	public String defaultFallback() {
      		return "默认提示:对不起,网络太拥挤了!";
      	}
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22

      当 user-service 正常提供服务时,访问与以前一致。但是当将 user-service 停机时,会发现页面返回了降级处理
      信息。

    2. 超时设置

      • Hystrix的默认超时时长为1,请求在超过1秒后都会返回错误信息,可以通过配置修改这个值。

        hystrix:
        	command:
        		default:
        			execution:
        				isolation:
        					thread:
        						#这是毫秒
        						timeoutInMilliseconds: 2000
        
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
五、服务熔断
  1. 熔断原理

    1.1 在服务熔断中,使用的熔断器,也叫断路器,其英文单词为:Circuit Breaker 熔断机制与家里使用的电路熔断原理类似;当如果电路发生短路的时候能立刻熔断电路,避免发生灾难。在分布式系统中应用服务熔断后;服务调用方可以自己进行判断哪些服务反应慢或存在大量超时,可以针对这些服务进行主动熔断,防止整个系统被拖垮。
    1.2 Hystrix的服务熔断机制,可以实现弹性容错;当服务请求情况好转之后,可以自动重连。通过断路的方式,将后续请求直接拒绝,一段时间(默认5秒)之后允许部分请求通过,如果调用成功则回到断路器关闭状态,否则继续打开,拒绝请求的服务。

  2. Hystrix的熔断状态机模型
    Hystrix的熔断状态机有3个状态:

    2.1 Closed:关闭状态(断路器关闭),所有请求都正常访问。
    2.2 Open:打开状态(断路器打开),所有请求都会被降级。Hystrix会对请求情况计数,当一定时间内失败请求百分比达到阈值,则触发熔断,断路器会完全打开。默认失败比例的阈值是50%,请求次数最少不低于20次。
    2.3 Half Open:半开状态,不是永久的,断路器打开后会进入休眠时间(默认是5S)。随后断路器会自动进入半开状态。此时会释放部分请求通过,若这些请求都是健康的,则会关闭断路器,否则继续保持打开,再次进行休眠计时。

  3. 熔断策略修改

    hystrix:
    	command:
    		default:
    			execution:
    				isolation:
    					thread:
    						#服务降级超时时间
    						timeoutInMilliseconds: 2000 
    			circuitBreaker:
    				# 触发熔断错误比例阈值,默认值50%
    				errorThresholdPercentage: 50 
    				# 熔断后休眠时长,默认值5秒
    				sleepWindowInMilliseconds: 10000 
    				# 熔断触发最小请求次数,默认值是20
    				requestVolumeThreshold: 10 
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Guff_9hys/article/detail/740984
推荐阅读
相关标签
  

闽ICP备14008679号