【微服务学习-- 组件】 熔断器Hystrix

发布时间 2023-07-14 09:31:56作者: 强仔123
一、什么是Hystrix
    由于在我们访问页面时,可能会通过服务注册中心,用一个服务去调用另外一个服务,但是可能由于网络原因或者超时访问等情况,导致一个或者一些服务堆积,这样就可能会导致其他服务受到影响甚至崩溃,这种导致服务堆积的现象就被称为雪崩。
        为了避免雪崩,Nestrix公司引入了一款防雪崩利器即Hystrix
        Hystrix具备服务降级、服务熔断、依赖隔离,监控等功能。

 

     服务降级:当某一请求不可用时,向接收方回复一个可以备选的响应,也就是我们在遇到网络不可达时,会出现,您要访问的页面跑丢了。(注意不是直接出现404,而是委婉的)。
                    导致服务降级的原因:1.程序发生异常   2.超时    3.服务熔断

 

二、演示
 
    1.建立Eureka服务注册中心,和普通的一样,就不加以展示。 端口号为9100
 
    2.建立Eureka-client-provider    端口号为:8083
 
        2.1 pom文件和application.yml都和之前的一样
 
        2.2 建立Testcontroller类,模拟在consumer调用provider时,产生异常和超时。

 

@RestController
public class TestController {
    /**
     * 这是在演示异常时的服务熔断
     * @return
     */
    @RequestMapping("/test")
    public String test(){
        int a=6/0;
        return "带有断路器的服务提供者";
    }

    /*
    演示的是超时异常   让该线程休眠200秒 但是  在consumer中进让其休眠2秒
     */
    @RequestMapping("/test02")
    public String test02(){
        try {
            Thread.sleep(200000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "带有熔断器的服务提供者";
    }
 
  3.建立Eureka_client_consumer模块,模拟消费者,会调用provider的注册的方法,模拟A服务调用B服务的过程。 端口号为 8086
 
        3.1 pom文件中引入Hystri依赖
 
<!--添加断路器的依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

    3.2 配置application.properties文件  开启健康检查

server.port=8086


spring.application.name=0704-pm-spring-cloud-hystrix-eureka-client-consumer


eureka.client.service-url.defaultZone=http://localhost:9100/eureka


#开启健康检查
management.endpoints.web.exposure.include=hystrix.stream
    
3.3  创建配置类 RestTemplateConfig:
 
            RestTemplate是一个用于进行HTTP请求的客户端工具,简化了Java程序中进行RESTful服务的调用过程。它是由spring-boot-starter-web引入的。
 
@Configuration
public class RestTemplateConfig {
    @Bean
    @LoadBalanced  //负载均衡
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

  

  3.4 加入熔断的处理类:MyHystrixCommand该类继承了HystrixCommand类  请注意这个类,之后将使用该类模拟现象

 

public class MyHystrixCommand extends HystrixCommand<String> {
    //请求对象
    private RestTemplate restTemplate;
    //请求的地址
    private String url;
    public MyHystrixCommand(Setter setter,RestTemplate restTemplate,String url){
        super(setter);
        this.restTemplate=restTemplate;
        this.url=url;
    }

    /**
     * 这个方法可以重写但是不能被手动调用
     * @return
     * @throws Exception
     */
    @Override
    protected String run() throws Exception {
        return restTemplate.getForObject(url,String.class);
    }




    /**
     * Fallback逻辑是在服务调用未能成功返回结果时执行的替代逻辑。
     * 它可以是一个预定义的默认值、一个备用的服务调用,
     * 或者其他的错误处理逻辑,
     * 以确保客户端能够得到一个合理的响应,
     * 而不会被异常中断。
     * @return
     */
    @Override
    public String getFallback() {
        return "error";//该方法就是我们要在控制器中定义的方法
    }
}
 
该类的作用是封装了需要保护的代码逻辑,实现对服务的熔断、降级和隔离。
 
        其中需要重写其中的run方法和fallback方法,run方法中定义的是需要进行熔断保护的逻辑
 
        fallback方法定义的是需要回退的代码逻辑。其中的返回值类型是String类型的,也就是我们需要定义在controller中的代码逻辑名。
 
        3.5 定义controller类 也是测试用例,在其中需要调用到来自provider的方法,来模拟服务调用过程,注意,此时在provider中添加的有异常和超时两种类型的错误。
    
@RestController
public class TestController {
    @Autowired
    private RestTemplate restTemplate;


    /*
    该方法是访问的controller的test01,但是在其中调用的是provider的test,如果中间出现错误
    异常或者是超超时, 就会调用fallback中的熔断方法
     */
    @HystrixCommand(fallbackMethod = "error")
    @RequestMapping("/test")
    public String test(){


        ResponseEntity<String> result = restTemplate.getForEntity("http://localhost:8083/0704-pm-spring-cloud-hystrix-eureka-client-provider/test", String.class);




        String body = result.getBody();
        return "这里是在consumer中调用了,使用了hystrix的服务";
    }


    @HystrixCommand(fallbackMethod = "error",commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds" ,value = "2000")
    })
    @RequestMapping("/test02")
    public String test02(){
        ResponseEntity<String> result = restTemplate.getForEntity("http://localhost:8083/0704-pm-spring-cloud-hystrix-eureka-client-provider/test02", String.class);


        String body = result.getBody();
        return "这里是在consumer中调用了,使用了hystrix的服务+"+body;


    }
    
    //断路器中的方法:
    public String error(Throwable throwable){
        System.out.println("********"+throwable.getClass());
        System.out.println("++++++++++"+throwable.getMessage());
        return "服务熔断了......";
    }
}
 
带背景颜色的 是我们在添加断路器之后的方法。
 
        3.6  在启动类 贴标签 开启短路检查:
 
@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker
public class Application {


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


}
 
开启服务,此时演示的是没有3.4的断路器以及3.5中的没有带背景颜色的情况。
 
    4.测试
 
        4.1    访问:http://localhost:9100/ 查看eureka注册情况:
 

 

可以看到provider已经注册成功。
 
        4.2 此时访问http://localhost:8083/test
 

  可以看到页面提示报错了那么我们再看控制台:

 

 

所以是我们当时建的那个6/0报错了,导致的异常
 
        4.3开启consumer
 
    访问http://localhost:9100/ 查看eureka注册情况:
 
        

 

  注册成功
 
        4.4访问  localhost:8086/test 因为此时没有加熔断器
 

 

            报错了 ,说明中间的跳转时,可能会有异常或者是超时的情况。
 
           4.5 将上边带有    背景颜色的代码进行接触  再进行演示。    
 
            4.6访问:localhost:8086/test
 

 

 

可以看到  页面显示的是我在控制器中定义的error(在熔断器中,getFallback返回值名字一致的方法)。
 
我们再去观察控制器的输出信息,因为我在controller的error方法中,我对错误信息进行了输出:
 
这个是在provider的报错信息

 

这个是在consumer中的报错信息

 

 

访问一下超时的情况: 访问:localhost:8086/test02
 

 

看一下控制台的报错信息:

 

因此 可以得出结论 熔断器可以起到降级服务扽作用。
 
 
 
三、在熔断器的基础上加上仪表盘dashboard
 
        在第二步的基础上进行展开。
 
5 .修改consumer的项目:    
 
        5.1 在consumer的项目中添加依赖:
 
<!--     健康的服务监控 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

     

    5.2 在consumer的配置文件中 开启健康检查 上边已经开启:

 

server.port=8086


spring.application.name=0704-pm-spring-cloud-hystrix-eureka-client-consumer


eureka.client.service-url.defaultZone=http://localhost:9100/eureka


#开启健康检查
management.endpoints.web.exposure.include=hystrix.stream

 

  6  、建立 client-dashboard模块:

 

  <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

 

  6.2 配置配置类:

 

server.port=2021 # 只配置一个端口号

 

6.3 设置 启动类 添加开启仪表盘的标签:

 

@SpringBootApplication
@EnableHystrixDashboard
public class Application {


    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
 
7.测试:
 
    一次开启Eureka-Server---> Eureka-Client-Provider --->Eureka-Client-Consumer  ---> Eureka-Hystrix ----> Eureka-Dasshboard
        
        7.1 访问:http://localhost:9100/ 查看eureka注册情况:
 

 

    7.2 访问:  http://localhost:8086/actuator/hystrix.stream
 
        因为此时没有访问接口,在页面中,会一直出现ping命令,因为此时,没有访问任何一个可能会有发生熔断的接口,因此会出现ping来表示正在进行健康检查的情况。
 
            7.3 先访问 http://localhost:8086/test 出发熔断命令后,在访问http://localhost:8086/actuator/hystrix.stream:
    

 

出现的是json格式的数据。
 
        7.4 访问 Hystrix Dashboard 可以直观的看到数据变化情况,
 

 

提交之后就会出现: