Spring Cloud学习(三)断路器Hystrix

本文详细介绍了Netflix开源的Hystrix组件,探讨了其在SpringCloud中的整合应用,包括服务隔离、熔断、降级等关键特性。通过实例展示了如何使用@EnableCircuitBreaker注解启用Hystrix,@HystrixCommand注解包裹方法,以及断路器的原理与配置参数,如快照时间窗、请求总数下限和错误百分比下限。

转载自:https://blog.youkuaiyun.com/forezp/article/details/69934399
    https://blog.youkuaiyun.com/liaokailin/article/details/51339357
    http://www.spring4all.com/article/948

  Netflix开源了Hystrix组件,Hystrix通过服务隔离、熔断(也可以称为断路)、降级等手段控制依赖服务的延迟与失败,SpringCloud对这一组件进行了整合。

  示例:

@SpringBootApplication
@EnableCircuitBreaker
@EnableHystrixDashboard //启动对hystrix的监控
public class Application {

    public static void main(String[] args) {
        new SpringApplicationBuilder(Application.class).web(true).run(args);
    }

}
@Component
public class CallDependencyService {

    private Random random = new Random();
    /**
     * 模拟获取用户信息(通过网络调用)
     * @return
     */
    @HystrixCommand(fallbackMethod = "fallback")
    public String mockGetUserInfo(){
        System.out.println("mockGetUserInfo(): " + Thread.currentThread().getName());
        int randomInt= random.nextInt(10) ;
        if(randomInt<8){  // 模拟调用失败情况
            throw new RuntimeException("call dependency service fail.");
        }else{
            return "UserName:"+randomInt;
        }
    }

    public String fallback(){
        System.out.println("fallback(): " + Thread.currentThread().getName());
        return "some exception occur call fallback method.";
    }
}
@Service
public class HystrixService {

    @Autowired
    private CallDependencyService dependencyService;

    public String callDependencyService() {
        return dependencyService.mockGetUserInfo();
    }
}
@RestController
public class HystrixController {

    @Autowired
    private HystrixService service;

    /**
     * 调用依赖的服务
     */
    @RequestMapping("/call")
    public String callDependencyService() {
        System.out.println("callDependencyService(): " + Thread.currentThread().getName());
        return service.callDependencyService();
    }
}

  @EnableCircuitBreaker或者@EnableHystrix表明启用hystrix,两个注解是等价的。
  @HystrixCommand表明该方法为hystrix包裹,可以对依赖服务进行隔离、降级、快速失败、快速重试等等hystrix相关功能 ,该注解属性较多,下面讲解其中几个:

fallbackMethod 降级方法
commandProperties 普通配置属性,可以配置HystrixCommand对应属性,例如采用线程池还是信号量隔离、熔断器熔断规则等等
ignoreExceptions 忽略的异常,默认HystrixBadRequestException不计入失败
groupKey() 组名称,默认使用类名称
commandKey 命令名称,默认使用方法名

  运行结果:

callDependencyService(): http-nio-9004-exec-1
mockGetUserInfo(): hystrix-CallDependencyService-1
fallback(): hystrix-CallDependencyService-1
callDependencyService(): http-nio-9004-exec-3
mockGetUserInfo(): hystrix-CallDependencyService-2
fallback(): hystrix-CallDependencyService-2
callDependencyService(): http-nio-9004-exec-5
mockGetUserInfo(): hystrix-CallDependencyService-3

  从运行日志可以看到,Hystrix会将方法调用放入Hystrix的线程池中去执行,因此在使用ThreadLocal的时候需要格外注意,当然也许会想到使用InheritableThreadLocal,但是这有一个很严重的问题,如果是在线程复用的情况下就会出问题,比如线程池中去使用inheritableThreadLocals进行传值,因为inheritableThreadLocals只是会再新创建线程的时候进行传值,线程复用并不会做这个操作。
  阿里开源的transmittable-thread-local,其主要功能就是解决在使用线程池等会缓存线程的组件情况下,提供ThreadLocal值的传递功能,解决异步执行时上下文传递的问题。如果想通过修改Hystrix源码来实现这个功能,参考 Spring Cloud中Hystrix 线程隔离导致ThreadLocal数据丢失(续)


断路器(Circuit Breaker)的理解
  “断路器”本身是一种开关装置,用于在电路上保护线路过载,当线路中有电器发生短路时,“断路器”能够及时的切断故障电路,防止发生过载、发热、甚至起火等严重后果。
  在分布式架构中,断路器模式的作用也是类似的,当某个服务单元发生故障,通过断路器的故障监控,直接切断原来的主逻辑调用。但是,在Hystrix中的断路器除了切断主逻辑的功能之外,还有更复杂的逻辑。
  断路器是在什么情况下开始起作用呢?这里涉及到断路器的三个重要参数:快照时间窗、请求总数下限、错误百分比下限。这个参数的作用分别是:

  • 快照时间窗:断路器确定是否打开需要统计一些请求和错误数据,而统计的时间范围就是快照时间窗,默认为最近的10秒。
  • 请求总数下限:在快照时间窗内,必须满足请求总数下限才有资格根据熔断。默认为20,意味着在10秒内,如果该hystrix命令的调用此时不足20次,即时所有的请求都超时或其他原因失败,断路器都不会打开。
  • 错误百分比下限:当请求总数在快照时间窗内超过了下限,比如发生了30次调用,如果在这30次调用中,有16次发生了超时异常,也就是超过50%的错误百分比,在默认设定50%下限情况下,这时候就会将断路器打开。

  那么当断路器打开之后会发生什么呢?先来说说断路器未打开之前,比如每个请求都会在当hystrix超时之后返回fallback,每个请求时间延迟就是近似hystrix的超时时间,如果设置为5秒,那么每个请求就都要延迟5秒才会返回。当熔断器在10秒内发现请求总数超过20,并且错误百分比超过50%,这个时候熔断器打开。打开之后,再有请求调用的时候,将不会调用主逻辑,而是直接调用降级逻辑,这个时候就不会等待5秒之后才返回fallback。通过断路器,实现了自动地发现错误并将降级逻辑切换为主逻辑,减少响应延迟的效果。
  在断路器打开之后,处理逻辑并没有结束,降级逻辑已经被成了主逻辑,那么原来的主逻辑要如何恢复呢?对于这一问题,hystrix也实现了自动恢复功能。当断路器打开,对主逻辑进行熔断之后,hystrix会启动一个休眠时间窗,在这个时间窗内,降级逻辑是临时的成为主逻辑,当休眠时间窗到期,断路器将进入半开状态,释放一次请求到原来的主逻辑上,如果此次请求正常返回,那么断路器将继续闭合,主逻辑恢复,如果这次请求依然有问题,断路器继续进入打开状态,休眠时间窗重新计时。


  Feign是自带断路器的,只需要在配置文件中配置打开它,在配置文件加以下代码:

# 开启hystrix
feign.hystrix.enabled=true

# hystrix调用方法的超时时间,默认是1000毫秒
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=5000
# 禁用Hystrix的超时时间
# hystrix.command.default.execution.timeout.enabled=false

  在启动类加上@EnableHystrix注解开启Hystrix,在FeignClient的HelloService接口的注解中加上fallback的指定类就行了:

@FeignClient(value = "COMPUTE-SERVICE",fallback = ServiceHystric.class)
public interface HelloService {

    @RequestMapping(value = "/add", method = RequestMethod.GET)
    Integer add(@RequestParam("a") Integer a, @RequestParam("b") Integer b);

}
@Component
public class ServiceHystric implements HelloService {

    @Override
    public Integer add(Integer a, Integer b) {
        return 1;
    }
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值