SpringBoot 服务熔断降级之-Hystrix

20 篇文章 0 订阅
17 篇文章 0 订阅

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. 线程隔离

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

  2. 服务降级

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

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

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

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

    @SpringBootApplication
    //eureka注册的注解
    @EnableDiscoveryClient
    @EnableCircuitBreaker
    public class ConsumerApplication {
    // ...
    }
    
    //特别的:注解@SpringCloudApplication等效于@SpringBootApplication、@EnableDiscoveryClient和@EnableCircuitBreaker三个注解
    
    
    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 "对不起,网络太拥挤了!";
      	}
      }
      
      

      @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 "默认提示:对不起,网络太拥挤了!";
      	}
      }
      
      

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

    2. 超时设置

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

        hystrix:
        	command:
        		default:
        			execution:
        				isolation:
        					thread:
        						#这是毫秒
        						timeoutInMilliseconds: 2000
        
        
五、服务熔断
  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 
    
    
  • 16
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot 提供了多种熔断降级的方式,最常见的是通过集成 Hystrix 或者 Resilience4j 来实现。 1. 使用 Hystrix:Hystrix 是 Netflix 开源的一款用于处理分布式系统的延迟和容错的库。在 Spring Boot 中,可以通过添加 Hystrix 的依赖来使用它。首先,在 pom.xml 文件中添加以下依赖: ```xml <dependencies> <!-- 引入 Hystrix 依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency> </dependencies> ``` 然后,在启动类上添加 `@EnableCircuitBreaker` 注解开启熔断降级功能。接下来,在需要进行熔断降级的方法上添加 `@HystrixCommand` 注解,并指定熔断时调用的备用方法。例如: ```java @Service public class MyService { @HystrixCommand(fallbackMethod = "fallbackMethod") public String myMethod() { // 执行业务逻辑 return result; } public String fallbackMethod() { // 备用方法逻辑 return fallbackResult; } } ``` 2. 使用 Resilience4j:Resilience4j 是一个轻量级的容错库,与 Hystrix 类似,可以用于处理分布式系统的故障。在 Spring Boot 中,可以通过添加 Resilience4j 的依赖来使用它。首先,在 pom.xml 文件中添加以下依赖: ```xml <dependencies> <!-- 引入 Resilience4j 依赖 --> <dependency> <groupId>io.github.resilience4j</groupId> <artifactId>resilience4j-spring-boot2</artifactId> <version>1.7.0</version> </dependency> </dependencies> ``` 然后,在需要进行熔断降级的方法上添加 `@RateLimiter`、`@CircuitBreaker` 或者其他相关注解,并配置相应的属性。例如: ```java @Service public class MyService { @CircuitBreaker(name = "myMethod", fallbackMethod = "fallbackMethod") public String myMethod() { // 执行业务逻辑 return result; } public String fallbackMethod(Throwable throwable) { // 备用方法逻辑 return fallbackResult; } } ``` 以上就是使用 Spring Boot 进行熔断降级的两种常见方式,根据具体需求和场景选择适合的方式进行使用。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值