Spring Cloud Hystrix断路器应用

1. Hystrix解决了什么问题

        复杂分布式体系结构中,应用程序会有多个依赖,甚至几十个依赖。每一个依赖都可不免的会在某个时候失败,如果主机应用程序没有于这些外部故障隔离开,它就会被搞垮的风险。对于一个依赖于30项服务的应用程序, 其中每项服务有99.99%的正常运行时间,那么正常运行时间就是99.99%的30次方,约等于99.7%。假设1年有10亿次请求,那么所有依赖都正常运行的时 0.3%失败就是3000000次。,如果每秒处理50个请求, 那么每个月失败请求时间累积约有5000秒的失败请求时间, 也就是83分钟的宕机时间 ,实际情况更糟糕,

正常情况下 用户请求按以下方式访问

很多后端系统中的一个节点出现问题后,它会阻止整个用户的请求,随着大量流量的出现可能导致所有服务器上的所有资源在几秒中内饱和,引起延迟增加,资源占用,导致整个系统中出现更多的级联故障

       Hystrix是一个类库,通过添加延迟容限和容错逻辑来帮助你控制这些分布式服务之间的交互。Hystrix通过隔离服务之间的访问点、停止跨服务的级联故障以及提供后备选项来实现这一点,所有这些都提高了系统的整体弹性,当使用Hystrix包装每个底层依赖项时,上面图表中显示的体系结构会发生变化。每个依赖项都是相互隔离的,受限于发生延迟时可能饱和的资源,并且包含在回退逻辑中,该逻辑决定当依赖项中发生任何类型的故障时做出什么响应

       Spirng Cloud Hystrix是基于Netflix的开源框架 Hystrix实现的,该框架的目的在于通过控制访问远程系统、服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力

2. Spring Cloud Hystrix 使用

参考代码: GitHub - PNZBEIJINGL/spring-cloud-lab  

服务 IP 端口
eureka-peer 127.0.0.1 1000 Eureka服务注册中心
ms-customer 127.0.0.1 8001 客户服务
ms-customer_interface 客户接口工程
ms-ribbon-consumer 127.0.0.1 8002 消费服务(测试调用客户服务)

2.1修改测试服务ms-ribbon-consumer

ms-ribbon-consumer工程需要引入spring-cloud-starter-hystrix 依赖

<!--引入Spring Cloud Hystrix 断路器 -->
<dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>

ms-ribbon-consumer工程主类增加注解@EnableCircuitBreaker ,注解用户开启断路器功能,当然也可以只使用@SpringCloudApplication注解来修饰主类,该注解定义包含使用的的@SpringBootApplication@EnableDiscoveryClient@EnableCircuitBreaker 三个注解

@EnableCircuitBreaker  //注解开启熔断功能
@EnableDiscoveryClient //将应用注册为Eureka客户端应用,激活Eureke中DiscoverClient实现,获得服务发现的能力
@SpringBootApplication
//@SpringCloudApplication
public class RibbonConsumerApplication {

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

    @Bean
    @LoadBalanced  //负载均衡
    RestTemplate resetTemplate(){
        return new RestTemplate();
    }
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public @interface SpringCloudApplication {
}

修改消费服务ConsumerQueryController ,增加注解HystrixCommand来指定回调方法getCustomerNameFallback,并实现回调方法

@RestController
public class ConsumerQueryController { 
     /**
     * http://127.0.0.1:8002/ribbon-consumer-name
     * 其中@HystrixCommand注解指定回调的方法
     * @return
     */
    @HystrixCommand(fallbackMethod = "getCustomerNameFallback")
    @RequestMapping(value = "/ribbon-consumer-name", method = RequestMethod.GET)
    public String testGetCustomerName() {
        ResponseEntity<String> responseEntity = restTemplate.getForEntity
                ("http://MS-CUSTOMER/customer/name/1", String.class, "1");
        return responseEntity.getBody();
    }

    public String getCustomerNameFallback(){
        return "getCustomerName ,因故障Hystrix熔断";
    }
    //.....
}

2.2修改被调用服务ms-customer

Hystrix默认的超时时间为2秒,所以使用Random对象随机生成0-4的数字,然后sleep几秒,通过随机数模拟一定几率发生超时触发断路 ,

@RestController()
@RequestMapping(path = "/customer")
public class CustomerController {

    private final Logger logger = Logger.getLogger(getClass());

    @Autowired
    private DiscoveryClient discoveryClient;


    /**
     * http://127.0.0.1:8001/customer/name/1
     */
    @RequestMapping(value = "/name/{id}", method = RequestMethod.GET)
    public String getCustomerName(@PathVariable("id") Long customerId) throws InterruptedException {
        //测试阻塞几秒
        int sleepTime=new Random().nextInt(3000);
        Thread.sleep(sleepTime);

        ServiceInstance instance = discoveryClient.getLocalServiceInstance();
        String message = " host:" + instance.getHost() + ",service_id:" + instance.getServiceId();
        logger.info(message);

        CustomerDTO customer = mockCustomer();
        return customer.getName();
    }

      private CustomerDTO mockCustomer() {
        CustomerDTO customer = new CustomerDTO();
        customer.setId(1000L);
        customer.setCode("1000");
        customer.setName("zhangsan");
        return customer;
    }

    //......
}

2.3测试验证

启动eureka-peer,ms-customer,ms-ribbon-consumer三个服务, 多次访问会出现以下结果,当超时返回的是getCustomerNameFallback函数返回的字符串 

 

3.Spring Cloud Hystrix Dashboard使用

参考代码: GitHub - PNZBEIJINGL/spring-cloud-lab  

服务 IP 端口
eureka-peer 127.0.0.1 1000 Eureka服务注册中心
hystrix-dashboard 127.0.0.1 2001 Hystrix仪表板
ms-customer 127.0.0.1 8001 客户服务
ms-customer_interface 客户接口工程
ms-ribbon-consumer 127.0.0.1 8002 消费服务(测试调用客户服务)

Spring Cloud 还完美的整合了它的仪表盘组件 Hystrix Dashboard ,它主要用来实时监控Hystrix的各项指标信息, 通过Hystrix Dashboard反馈的实时信息,可以帮助我们快速发现系统中存在的问题。

3.1 构建hystrix-dashboard应用

创建一个标准的Spring Boot工程,命名为hystrix-dashboard,pom文件参考如下

  <dependencies>

        <!--引入Spring Cloud Hystrix 断路器 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
        </dependency>

        <!--引入Spring Cloud Hystrix 断路器监控仪表盘-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
        </dependency>

        <!--引入Spring Boot 监控-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

    </dependencies>

启动类中增加注解@EnableHystrixDashboard 启动Hystrix Dashboard功能

@EnableHystrixDashboard //启动HystrixDashboard功能
@SpringBootApplication
public class HystrixDashboardApplication {

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

}

修改配置application.properties设置服务端口

spring.application.name=hystrix-dashboard
server.port=2001

测试Hystrix仪表盘

访问 http://127.0.0.1:2001/hystrix 查看Hystrix 监控首页

 从页面文字我们可以知道,Hystrix Dashboard共支持三种不同的监控方式

  • Cluster via Turbine (default cluster): 默认的集群监控:访问http://turbine-hostname:port/turbine.stream
  • Cluster via Turbine (custom cluster): 指定的集群监控:访问http://turbine-hostname:port/turbine.stream?cluster=[clusterName]
  • Single Hystrix App: 单体应用监控:访问 http://hystrix-app:port/hystrix.stream

3.2被监控的服务ms-ribbon-consumer

修改内容:

  • pom中增加依赖
  • 启动主类上增加了注解@EaableCircuitBreaker
        <!--引入Spring Cloud Hystrix 断路器 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
        </dependency>

        <!--引入监控模块 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
@EnableCircuitBreaker  //注解开启熔断功能
@EnableDiscoveryClient //将应用注册为Eureka客户端应用,激活Eureke中DiscoverClient实现,获得服务发现的能力
@SpringBootApplication
public class RibbonConsumerApplication {

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

    @Bean
    @LoadBalanced  //负载均衡
    RestTemplate resetTemplate(){
        return new RestTemplate();
    }

}

3.3 测试被监控服务

第一步:启动eureka-peer,ms-customer,ms-ribbon-consumer,hystrix-dashboard四个服务后, 访问 http://127.0.0.1:2001/hystrix 查看Hystrix 监控首页

从首页中我们知道单体监控方式为 Single Hystrix App: 单体应用监控:访问 http://hystrix-app:port/hystrix.stream

第二步: 我们监控的ms-ribbon-consumer应用,其IP和端口是 127.0.0.1:8002, 因此在页面中输入http://127.0.0.1:8002/hystrix.stream

 点击Monitor Stream查看结果

图示说明(下方图片来自网络)

3.4仪表盘常见问题

问题1:Unable to connect to Command Metric Stream

问题原因:

1)可能是访问地址拼写不正确,注意hystrix.stream是否拼写正确,字母r的位置是否正确

2)可能是输入的地址端口不正确: 测试时修改目标服务端口为8002, 没有注意访问时设置路径仍然访问8009 ,引起问题

3)可能是监控的目标服务没有引入spring-boot-starter-actuator启动监控依赖

问题2 ,页面输入监控端口后,界面一直是 loading,访问http://127.0.0.1:8002/hystrix.stream,全是ping调用无信息

 问题原因

1)可能是没有调用过接口,所以一直是加载状态, 当使用消费应用 ms-ribbon-consumer 调用一次接口后,重新访问后就会显示监控信息

问题3. not in the allowed list of proxy host name(网络上看到的问题)

Origin parameter: http://localhost:1001/actuator/hystrix.stream is not in the allowed list of proxy host names.  
If it should be allowed add it to 
hystrix.dashboard.proxyStreamAllowList.
2021-02-08 20:35:26.394  WARN 1920 --- [nio-8000-exec-5] ashboardConfiguration$ProxyStreamServlet : 

处理方法:增加配置 

hystrix:
  dashboard:
    proxy-stream-allow-list: "localhost"

问题4.请求监控仪表盘首页报错404 (网络上看到的问题)

Srping Boot 2.0以后仪表盘的默认路径不在是 /hystrix.stream,这时就需要我们自己去设置,在主类中添加以下代码

import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ServletConfigBean {
   @Bean
    public ServletRegistrationBean hystrixMetricsStreamServlet() {
        ServletRegistrationBean regist = new ServletRegistrationBean();
        regist.setServlet(new HystrixMetricsStreamServlet());
        regist.setName("hystrixMetricsStreamServlet");
        regist.setLoadOnStartup(1);
        regist.addUrlMappings("/hystrix.stream");
        return regist;
    }
}

   

   

     

  上一篇: Spring Cloud Ribbon负载均衡策略详解 

猜你喜欢

转载自blog.csdn.net/Beijing_L/article/details/121241828