6、Spring Cloud -熔断器Hystrix

 6.1、什么是Hystrix

在分布式系统中、服务与服务之间的依赖错综复杂,一种不可避免的情况就是某些服务
出现故障,导致依赖于它们的其他服务出现远程调度的线程阻塞。
 
Hystrix是Netflix 公司开源的一个项目,它提供了熔断器功能
能够阻止分布式系统中出现联动故障
 
Hystrix 是通过隔离服务的访问点阻止联动故障的,并提供了故障的解决方案,从而提高了
整个分布式系统的弹性

 

 

6.2、Hystrix解决了什么问题

在复杂的分布式系统中,可能有几十个服务相互依赖,这些服务由于某些原因:
机房的不可靠性、网络服务商的不可靠性 ,导致某个服务不可用等
 
如果系统不隔离该不可用的服务,可能会导致整个系统不可用
 
对于依赖 30 个服务的应用程序,每个服务的正常运行时间为 99.99%
对于单个服务来说, 99.99% 的可用是非常完美的
 
99.9930 = 99.7% 的可正常运行时间和 0.3% 的不可用时间,那么 10 亿次请求中有 3000000
次失败,实际的情况可能比这更糟糕。
 
如果不设计整个系统的韧性,即使所有依赖关系表现良好,单个服务只有 0.01% 的不可用,
由于整个系统的服务相互依赖,最终对整个系统的影响是非常大的
 
在微服务系统中,一个用户请求可能需要调用几个服务才能完成
 
在所有的服务都处于可用状态时, 一个用户请求需要调用A、H 、I 、P服务

 

 

 

 6.3、Hystrix的设计原则

 设计原则如下:

 

 

 6.4、Hystrix的工作机制

 如图:

 

首先,当服务的某个 API 接口的失败次数
在一定时间内小于设定的阀值时,熔断器处于关闭状态,该 API 接口正常提供服务
 
当该API 接口处理请求的失败次数大于设定的阀值时, Hystrix 判定该 API 接口出
现了故障,打开熔断器,这时请求该 API 接口会执行快速失败的逻辑(即 fall back
回退的逻辑),不执行业务逻辑,请求的线程不会处于阻塞状态。
 
处于打开状态的熔断器,一段时间后会处于半打开状态,并将 定数量的请求执行正常逻辑。
 
剩余的请求会执行快速失败,若执行正常逻辑的请求失败了,则熔断器继续打开,若成功了 ,
则将熔断器关闭。这样熔断器就具有了自我修复的能力。

 

搭建工程

新建工程:

pom依赖:

<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.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

 

 

RibbonConfig.java 

@Configuration
public class RibbonConfig {
    @Bean
    @LoadBalanced
    RestTemplate restTemplate(){
        return  new RestTemplate();
    }
}

 

 

hystrixService.java

@Service
public class hystrixService {
    @Autowired
    RestTemplate restTemplate;

    public String port(){
        return restTemplate.getForObject("http://CLINET/port",String.class);
    }
}

 

 

hystrixController.java

@RestController
public class hystrixController {

    @Autowired
    hystrixService hystrixService;

    @GetMapping("/hi")
    public  String hi(){
        return hystrixService.port();
    }

}

 

 

主配置类:
@EnableDiscoveryClient
@SpringBootApplication
public class HystrixApplication {
    public static void main(String[] args) {
        SpringApplication.run(HystrixApplication.class, args);
    }
}
测试时可以成功访问两个client

 

6.5、在RestTemplate和Ribbon 上使用熔断器

1、首先引入相关的依赖

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

 

2、主配置类加上@EnzbleHystrix注解开启Hystrix的熔断功能

@EnableDiscoveryClient
@SpringBootApplication
@EnableHystrix
public class HystrixApplication {

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

 

修改hystrixService.java中的方法port()方法
@HystrixCommand注解,port()方法就启用 Hystrix 熔断器的功能
fallbackMethod属性为处理回退逻辑的方法
在熔断器打开的状态下,会执行 fallback 逻辑。

 

fallback 的逻辑最好是返回一些静态的字符串,不需要处理复杂的逻辑,也不需要远程调度其
他服务,这样方便执行快速失败,释放线程资源

 

hystrixService.java

@Service
public class hystrixService {
    @Autowired
    RestTemplate restTemplate;


    @HystrixCommand(fallbackMethod = "isError")
    public String port(){
        return restTemplate.getForObject("http://CLINET/port",String.class);
    }

    public String isError(){
        return "request is error!";
    }

}
在测试中:
关闭服务提供者

 

观察浏览器会显示:

 

6.6、在Feign上使用熔断器

Feign 的起步依赖中已经引入了 Hystrix 的依赖
所以在 Feign 中使用 Hystrix 不需要引入任何的依赖

 

使用之前的工程:

地址:https://www.cnblogs.com/Mrchengs/p/10646137.html

新建一个类:

portHystrix.java

需要实现接口中的方法

@Component
public class portHystrix implements EurekaClientFeign {
    @Override
    public String port() {
        return "request is wrong!!";
    }
}
portHystrix作为容器的逻辑处理类,需要实现EurekaClientFeign接口
并在接口中实现方法作为处理熔断逻辑的方法

 

EurekaClientFeign.java

@FeignClient(value = "CLINET",configuration = feignconfig.class,
fallback = portHystrix.class)
public interface EurekaClientFeign {
    @GetMapping("/port")
    String port();
}

 

在@FeignClient 注解的fallback 配置加上快速失败的处理类
该 理类是作为 Feign 熔断器的逻辑处理类
必须实现被@FeignClient 修饰的接口。

 

配置文件中:

spring.application.name=feign
server.port=8088
eureka.client.service-url.defaultZone=http://localhost:8762/eureka/

#开启Hystrix的功能
feign.hystrix.enabled=true

 

正常开启:

此时可以进行访问!!!

 

6.7、使用Hystrix Dashboard监控熔断器的状态

微服务架构中 ,为了保证服务实例的可用性,防止服务实例出现故障导致线程阻塞
出现了熔断器模型。
 
烙断器的状况反映了一个程序的可用性和健壮性,它是一个重要指标
 
Hystrix Dashboard 是监控 Hystrix 的熔断器状况的一个组件,提供了数据监控和 友好的图形化
展示界面。

6.7.1、在RestTemplate中使用Hystrix Dashboard

添加所需要的依赖:

<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</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>

 

 

在主配置类中:
开启Hystrix Dashboard 的功能
@EnableCircuitBreaker
@EnableHystrixDashboard
@EnableDiscoveryClient
@SpringBootApplication
@EnableHystrix
public class HystrixApplication {

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

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

坑位......

 

此时把服务提供者和注册中心均开启:

 

浏览器上输入:
会一直进行刷新

 

 当访问:

 

在观察:
数据指标图:会一直刷新

 

浏览器访问:

 

 

 

 此时发现:

 

在该页面显示了熔断器的各种数据指标

 

 6.7.2、Feign 中使用 Hystrix Dashboard

1、pom文件

<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.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</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</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>

 

 

主配置类:

@EnableHystrix
@EnableHystrixDashboard
@EnableFeignClients(basePackages = "com.cr.eurekafeignclient.feign")
@EnableDiscoveryClient
@SpringBootApplication
public class EurekaFeignClientApplication {

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


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

 

 其余的测试都和之前相似

 

posted @ 2019-04-03 20:40  MrChengs  阅读(303)  评论(0编辑  收藏  举报