在分布式环境中,服务之间的依赖调用正常情况下如下图:
image.png
但是,分布式环境中服务的宕机,超时是经常发生的,为了不导致分布式服务的雪崩效应,Hystrix在对服务的调用增加的延迟和容错逻辑。
image.png

熔断触发降级

  • 熔断的目的是为了起到保护服务的作用
  • 降级
    • 主动降级,大促的时候关闭非核心服务.
    • 被动降级, 熔断降级、限流降级

要使用Hystrix在pom文件中添加依赖

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
  4. </dependency>

Api方式使用Hystrix

  1. // 自定义一个HystrixCommand实现
  2. public class HystrixService extends HystrixCommand<String> {
  3. // 要执行的任务
  4. private Supplier<String> supplier;
  5. //
  6. public HystrixService(HystrixCommandGroupKey group, Supplier<String> supplier) {
  7. this(group, 3000);
  8. this.supplier = supplier;
  9. }
  10. private HystrixService(HystrixCommandGroupKey group, int executionIsolationThreadTimeoutInMilliseconds) {
  11. super(group, executionIsolationThreadTimeoutInMilliseconds);
  12. }
  13. // 执行封装的业务
  14. @Override
  15. protected String run() throws Exception {
  16. return supplier.get();
  17. }
  18. // 降级调用的方法
  19. @Override
  20. protected String getFallback() {
  21. return "fallback";
  22. }
  23. }

使用

@RestController
@RequestMapping("/api/v0")
public class HystrixController {
    @Autowired
    private RestTemplate restTemplate;

    // 普通请求
    @GetMapping("/baidu/1")
    public Object helloBaidu1() {
        String forObject = restTemplate.getForObject("https://www.baidu.com", String.class);
        return forObject;
    }

    // 带熔断的请求
    @GetMapping("/baidu/2")
    public Object helloBaidu2() {
        // 静态代理
        HystrixService hystrixService = new HystrixService(
            HystrixCommandGroupKey.Factory.asKey("outerServer"),// 资源分组隔离
            () -> restTemplate.getForObject("https://www.baidu.com", String.class)
        );
        // 执行模板方法
        return hystrixService.execute();
    }
}

HystrixCommand#execute()

public R execute() {
    try {
        return queue().get();
    } catch (Exception e) {
        throw Exceptions.sneakyThrow(decomposeException(e));
    }
}

注解方式

//注解方式
@HystrixCommand(commandProperties =
                {
                    @HystrixProperty(name = "circuitBreaker.enabled", value = "true"),// 开启熔断
                    @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "5"),// 10秒内最小请求量
                    @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "5000"),//熔断时间窗口
                    @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50"),// 错误百分比
                    @HystrixProperty(name = "execution.timeout.enabled", value = "true"),// 调用超时开启
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000"),// 调用超时
                },
                fallbackMethod = "fallbackBaidu"// 降级调用方法
               )
@GetMapping("baidu3")
public Object helloBaidu3() {
    try {
        TimeUnit.SECONDS.sleep(5);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    String forObject = restTemplate.getForObject("https://www.baidu.com", String.class);
    return forObject;
}

// 降级方法,同一个类中
public Object fallbackBaidu() {
    return "fallbackBaidu";
}

同时需要在启动类上加上@EnableHystrix或则@@EnableCircuitBreaker

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Import(EnableCircuitBreakerImportSelector.class)
public @interface EnableCircuitBreaker {

}

@Order(Ordered.LOWEST_PRECEDENCE - 100)
public class EnableCircuitBreakerImportSelector extends
        SpringFactoryImportSelector<EnableCircuitBreaker> {

    @Override
    protected boolean isEnabled() {
        return getEnvironment().getProperty("spring.cloud.circuit.breaker.enabled", Boolean.class, Boolean.TRUE);
    }

}

结合spirngcloud配置方式使用