Hystrix是什么

在分布式环境中,许多服务依赖项中的一些必然会失败。Hystrix是一个库,通过添加延迟容忍和容错逻辑,帮助你控制这些分布式服务之间的交互。Hystrix通过隔离服务之间的访问点、停止级联失败和提供回退选项来实现这一点,所有这些都可以提高系统的整体弹性

Hystrix目的是什么

hystrix的目标是:

  1. 对通过第三方客户端库访问的依赖项(通常是通过网络)的延迟和故障进行保护和控制。
  2. 在复杂的分布式系统中阻止级联故障。
  3. 快速失败,快速修复。
  4. 回退,尽可能优雅的降级。
  5. 启用近实时监控、警报和操作控制。

    Hystrix的设计原则

  • 防止任何单个依赖项耗尽所有容器用户线程。
  • 甩掉保护,快速失败而不是排队。
  • 在任何可行的地方提供回退,以保护用户不受失败的影响。
  • 使用隔离技术(如隔离板、泳道和断路器模式)来限制任何一个依赖项的影响。
  • 通过近实时的度量、监视和警报来优化发现时间。
  • 通过配置的低延迟传播来优化回复时间。
  • 支持对Hystrix的大多数方面的动态属性修改,允许使用低延迟反馈循环进行实时操作修改。
  • 避免在整个依赖客户端执行中出现故障,而不仅仅是在网络流量中。

    Hystrix的实现

  1. 用一个HystrixCommand 或者 HystrixObservableCommand (这是命令模式的一个例子)包装所有的对外部系统(或者依赖)的调用,典型地它们在一个单独的线程中执行。
  2. 调用超时时间比你自己定义的阈值要长。有一个默认值,对于大多数的依赖项你是可以自定义超时时间的。
  3. 为每个依赖项维护一个小的线程池(或信号量);如果线程池满了,那么该依赖性将会立即拒绝请求,而不是排队。
  4. 调用的结果有这么几种:成功、失败(客户端抛出异常)、超时、拒绝。
  5. 在一段时间内,如果服务的错误百分比超过了一个阈值,就会触发一个断路器来停止对特定服务的所有请求,无论是手动的还是自动的。
  6. 当请求失败、被拒绝、超时或短路时,执行回退逻辑。
  7. 近实时监控指标和配置变化。

    Hystrix服务超时降级

    引入pom文件。
    1. <dependency>
    2. <groupId>org.springframework.cloud</groupId>
    3. <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    4. <version>2.2.1.RELEASE</version>
    5. </dependency>
    修改配置文件,启动hystrix。
    feign:
    hystrix:
     enabled: true
    
    修改服务启动类。
    ```java package com.atguigu.springcloud;

import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.context.annotation.Bean;

@SpringBootApplication @EnableEurekaClient @EnableCircuitBreaker public class Application {

public static void main(String[] args) {
    SpringApplication.run(Application.class,args);
}

}

配置服务降级规则。
```java
@HystrixCommand(fallbackMethod = "paymentInfo_TimeoutHandler",commandProperties = {
        @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "5000")
})
public String paymentInfo(Integer id){
//        int age=10/0;
    try {
        TimeUnit.SECONDS.sleep(3);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return "线程池: "+Thread.currentThread().getName()+"paymentInfo_OK,Id:  "+id+"\t"+"haha";
}

public String paymentInfo_TimeoutHandler(Integer id){
    return "线程池: "+Thread.currentThread().getName()+"8001系统繁忙,Id:  "+id+"\t"+"/(ㄒoㄒ)/~~";
}

Hystrix之全局服务降级

通过注解@DefaultProperties,在方法上面添加@HystrixCommand注解。

package com.atguigu.springcloud.controller;

import com.atguigu.springcloud.service.PaymentHystrixService;
import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
@DefaultProperties(defaultFallback = "payment_Global_FallbackMethod")
public class PaymentHystrixController {

    @Autowired
    private PaymentHystrixService paymentHystrixService;

    @GetMapping("/consumer/payment/hystrix/ok/{id}")
    public String paymentInfo_OK(@PathVariable("id") Integer id){
        return paymentHystrixService.paymentInfo_OK(id);
    }

    @GetMapping("/consumer/payment/hystrix/timeout/{id}")
    @HystrixCommand
    public String paymentInfo(@PathVariable("id") Integer id){
        return paymentHystrixService.paymentInfo(id);
    }


    public String payment_Global_FallbackMethod(){
        return "Global异常信息处理,请稍后再试";
    }

}

Hystrix之通配服务降级

新建feign服务接口,指定fallback类。

package com.atguigu.springcloud.service;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@Component
@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT",fallback = PaymentFallbackService.class)
public interface PaymentHystrixService {

    @GetMapping("/payment/hystrix/ok/{id}")
    public String paymentInfo_OK(@PathVariable("id") Integer id);

    @GetMapping("/payment/hystrix/timeout/{id}")
    public String paymentInfo(@PathVariable("id") Integer id);

}

新建该接口的实现类,该类的方法就是对应的fallback方法。

package com.atguigu.springcloud.service;

import org.springframework.stereotype.Service;

@Service
public class PaymentFallbackService implements PaymentHystrixService {

    @Override
    public String paymentInfo_OK(Integer id) {
        return "服务器奔溃了,请稍后再试";
    }

    @Override
    public String paymentInfo(Integer id) {
        return "uzi倒了,请稍后再试";
    }

}

Hystrix之DashBoard

引入pom文件。

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
    <version>2.2.1.RELEASE</version>
</dependency>

配置主启动类。

package com.atguigu.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;

@SpringBootApplication
@EnableHystrixDashboard
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);

    }

}

配置要控服务的主启动类(我们这里是8001)。

package com.atguigu.springcloud;

import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
    }

    @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://localhost:9001/hystrix。