背景
现在我们自己有一个服务A,需要依赖第三方的服务B,由于第三方的资源问题,导致我们在高峰期的时候调用第三方的时候总是出现超时未返回的现象,由于服务B给我们提供了较多的接口,其中有个别的接口属于比较重要的接口不能阻断,为了在高峰期的时候不影响其中几个重要接口的处理速度,在服务A上面针对非重要接口进行的限流降级策略来削峰,尽量保证重要接口的响应,并且走fallback降级逻辑,返回对应的业务处理结果。正好使用的就是springcloud 中的hystrix框架。
一、Hystrix(具体就不介绍了)
Hystrix被设计的目标是:
- 对通过第三方客户端库访问的依赖项(通常是通过网络)的延迟和故障进行保护和控制。
- 在复杂的分布式系统中阻止级联故障。
- 快速失败,快速恢复。
- 回退,尽可能优雅地降级。
- 启用近实时监控、警报和操作控制。
二、Hystrix 隔离策略细粒度控制
Hystrix 实现资源隔离,有两种策略:
- 线程池隔离(默认):是用 Hystrix 自己的线程去执行调用,适合绝大多数场景,比如说我们对依赖服务的网络请求的调用和访问、需要对调用的 timeout 进行控制(捕捉 timeout 超时异常)
- 信号量隔离:是直接让 tomcat 线程去调用依赖服务,信号量有多少,就允许多少个 tomcat 线程通过它,然后去执行。适合你的访问不是对外部依赖的访问,而是对内部的一些比较复杂的业务逻辑的访问,并且系统内部的代码,其实不涉及任何的网络请求,那么只要做信号量的普通限流就可以了,因为不需要去捕获 timeout 类似的问题。
三、实战
依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.1.2.RELEASE</version>
</dependency>
代码
package com.example.demo.service;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
* @author 2019/9/14 18:05
*/
@Service
@Slf4j
public class HystrixServiceImpl {
@HystrixCommand(
fallbackMethod = "fallBackTestHystrix",
threadPoolProperties = { //10个核心线程池,超过20个的队列外的请求被拒绝; 当一切都是正常的时候,线程池一般仅会有1到2个线程激活来提供服务
@HystrixProperty(name = "coreSize", value = "10"),
@HystrixProperty(name = "maxQueueSize", value = "100"),
@HystrixProperty(name = "queueSizeRejectionThreshold", value = "20")},
commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "500"), //命令执行超时时间
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "2"), //若干10s一个窗口内失败三次, 则达到触发熔断的最少请求量
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "5000") //断路30s后尝试执行, 默认为5s
})
// @HystrixCommand(fallbackMethod = "fallBackTestHystrix",
// commandProperties = {
// @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "500"),
// @HystrixProperty(name = "execution.isolation.semaphore.maxConcurrentRequests", value = "9"),
// @HystrixProperty(name = "fallback.isolation.semaphore.maxConcurrentRequests", value = "20"),
// @HystrixProperty(name = "execution.isolation.strategy", value ="SEMAPHORE")
// })
// @HystrixCommand(fallbackMethod = "hiFail", commandProperties = {
// @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "500")
// },
// threadPoolProperties = {
// @HystrixProperty(name = "coreSize", value = "10"),
// @HystrixProperty(name = "maxQueueSize", value = "20"),
// @HystrixProperty(name = "keepAliveTimeMinutes", value = "0"),
// @HystrixProperty(name = "queueSizeRejectionThreshold", value = "15"),
// @HystrixProperty(name = "metrics.rollingStats.numBuckets", value = "12"),
// @HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "1440")
// })
public String testHystrix(){
try {
log.info("开始睡眠");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("is commom testHystrix");
return "is commom testHystrix";
}
public String fallBackTestHystrix(){
log.info("走降级策略");
return "is fallBackTestHystrix";
}
}