vlambda博客
学习文章列表

hystrix停更了,我该何去何从...

一. 背景:

Hystrix Status


Hystrix is no longer in active development, and is currently in maintenance mode.

Hystrix (at version 1.5.18) is stable enough to meet the needs of Netflix for our existing applications. Meanwhile, our focus has shifted towards more adaptive implementations that react to an application’s real time performance rather than pre-configured settings (for example, through adaptive concurrency limits). For the cases where something like Hystrix makes sense, we intend to continue using Hystrix for existing applications, and to leverage open and active projects like resilience4j for new internal projects. We are beginning to recommend others do the same.

    目前来看,Hystrix是比较稳定的,并且Hystrix只是停止开发新的版本,并不是完全停止维护,Bug什么的依然会维护的。因此短期内,Hystrix依然是继续使用的。

但从长远来看,Hystrix总会达到它的生命周期,那么Spring Cloud生态中是否有替代产品呢?

可以采用的有比如Alibaba Sentinal/Resilience4J下面来谈一谈各个之间的差异

二. Hystrix介绍:

    Hystrix 是一个用于处理分布式系统的延迟和容错的开源库, 在分布式系统中,许多不可避免的调用会失败, 比如超时,异常等。Hystrix 能够保证在一个依赖出现问题的情况下,不会导致整体服务失败,避免级联故障,提高分布式系统的弹性。

“断路器” 本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似保险熔断),向调用方法返回一个符合预期的,可处理的被选相应(FallBack), 而不是长时间的等待或者跑出调用方法无法处理的异常,这样就保证了服务调用方的线程不会长时间,不必要地占用,从而避免了故障在分布式系统中国呢的蔓延,从而导致雪崩效应。

Hystrix的主要作用有服务隔离、服务熔断、服务降级

2.1 Hystrix的服务降级

服务降级是指当请求后端服务出现异常的时候, 可以使用fallback方法返回的值

解决场景:服务超时,出错

  • 对方服务器超时了,调用者不能一直死等,必须有服务降级

  • 对方服务器宕机了,调用者不能卡死等待,必须有服务降级

  • 对方服务OK,调用者自己出现故障(自己等待时间小于服务器超时时间,自己要求服务降级)

代码参见:

https://github.com/xingchunjing/springcloud2020

猿生日记-jxc

客户端:pom文件添加依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

客户端:yml文件配置

ribbon:
  # 指的是建立链接所用的时间,适用于网络状况正常的情况下,两端链接所用的时间
  ReadTimeout: 9000
  # 指的是建立链接后从服务器读取可用资源所用的时间
  ConectTimeout: 9000
feign:
  hystrix:
    enabled: true

客户端:主启动类

//开启OpenFeign功能
@EnableFeignClients
//开启服务降级功能
@EnableCircuitBreaker

客户端:配置文件降级参数

超时时间15秒,ribbon链接时间9秒,服务端会进行一次轮询

@Configuration
@ConditionalOnClass({ HystrixCommand.class, HystrixFeign.class })
public class HystrixFeignConfiguration {

    @Bean
    @Scope("prototype")
    @ConditionalOnMissingBean
    @ConditionalOnProperty(name = "feign.hystrix.enabled", matchIfMissing = true)
    public Feign.Builder feignHystrixBuilder() {
        return HystrixFeign.builder().setterFactory(new SetterFactory() {
            @Override
            public HystrixCommand.Setter create(Target<?> target, Method method) {
                return HystrixCommand.Setter
                        .withGroupKey(HystrixCommandGroupKey.Factory.asKey(FeignConsumerService.class.getSimpleName()))// 控制 MessageService 下,所有方法的Hystrix Configuration
                        .andCommandPropertiesDefaults(
                                HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(15000// 超时配置
                        );
            }
        });
    }
}

客户端配置文件降级返回

@Component//不要忘记添加
public class DeptClientServiceFallbackFactory implements FallbackFactory<FeignConsumerService>{
    @Override
    public FeignConsumerService create(Throwable throwable) {

        return new FeignConsumerService() {

            @Override
            public String providerFe(Integer id) {
                return null;
            }

            @Override
            public String providerHystrix(Integer id) {
                return "客户端执行超时,调用服务降级方法~"+id+"---------"+System.currentTimeMillis()/1000;
            }
        };

    }
}

客户端:controller/service

fallbackFactory要与降级返回配置文件一致

@RestController
public class FeignConsumerController {

    @Autowired
    private FeignConsumerService feignConsumerService;

    @GetMapping("/consumer/feign/{id}")
    public String consumerNa(@PathVariable Integer id){
        return feignConsumerService.providerFe(id);
    }

    @GetMapping("/consumer/hystrix/{id}")
    public String consumerHystrix(@PathVariable Integer id){
        System.out.println(System.currentTimeMillis()/1000);
        return feignConsumerService.providerHystrix(id);
    }
}

@Component
@FeignClient(value = "cloud-provider-gesoten",fallbackFactory = DeptClientServiceFallbackFactory.class)
public interface FeignConsumerService {

    @GetMapping("/test/feign/{id}")
    String providerFe(@PathVariable("id") Integer id);


    @GetMapping("/test/hystrix/{id}")
    String providerHystrix(@PathVariable("id")Integer id);
}

服务端配置较为简单,只需要添加注解即可

@Override
@SneakyThrows
@HystrixCommand(fallbackMethod = "payInfoTimeOutHandler", commandProperties = {
        @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "10000")

})
public String providerHystrix(Integer id) {
    System.out.println("进入服务端:8001========>"+System.currentTimeMillis()/1000);
    int timeNumber = 11;
    TimeUnit.SECONDS.sleep(timeNumber);
    return "Hystrix test" + "\tid "+ id+"\n"+ UUID.randomUUID().toString();
}


public String payInfoTimeOutHandler(Integer id) {
    System.out.println("服务端超时:8001========>"+System.currentTimeMillis()/1000);
    return "服务端执行超时,调用服务降级方法~"+id;
}

2.2 Hystrix的服务熔断

断路器关闭条件:

  • 当满足一定的阙值的时候(默认10秒内超过20次请求)

  • 当失败率达到一定的时候,默认10秒内超过50%的请求失败

  • 达到以上阙值,断路器开启

  • 当开启的时候所有请求都不会进行转发

  • 一段时间后(默认5秒),这个时候断路器是半开状态,会让一个请求转发,测试是否成功

@SneakyThrows
@HystrixCommand(fallbackMethod = "paymentCircuitBreakerHandler", commandProperties = {
        // 是否开启断路器
        @HystrixProperty(name = "circuitBreaker.enabled", value = "true")
,
        // 请求次数
        @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),
        // 时间窗口
        @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"),
        // 失败率达到多少
        @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60")
})
@Override
public String paymentCircuitBreaker(Long id) {
    int timeNumber = 5;
    TimeUnit.SECONDS.sleep(timeNumber);
    return "正常执行完毕~";
}

public String paymentCircuitBreakerHandler(Long id) {
    return "执行超时,调用服务熔断方法~";
}

2.3 Hystrix的服务监控

pom依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId> spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>

启动类

//类注解
@EnableHystrixDashboard


/**
 *  此配置是为了服务监控而配置,与服务容错本省无关,spring-cloud 升级后的坑
 *  ServletRegistrationBean 因为 spring boot 的默认路径不是 "/hystrix.stream"
 *  只要在自己的项目里配置下文的 servlet 就可以了
 * @return
 */

@Bean
public ServletRegistrationBean getServlet() {
    HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
    ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
    registrationBean.setLoadOnStartup(1);
    registrationBean.addUrlMappings("/hystrix.stream");
    registrationBean.setName("HystrixMetricsStreamServlet");
    return registrationBean;
}

笔者代码:http://cloud-consumer-feign/hystrix

进入后:

hystrix停更了,我该何去何从...

三.最后:

    Hystrix已经停止更新了,我们不能停止学习呀,加油奥利给,我们有更好的工具Sentinel,后面会整理Sentinel的具体应用...