hystrix的简单使用

1. 本章重点:

口 什么是Hystrix 。
口 Hystrix 解决了什么问题。
口 Hystrix 的工作原理。
口 如何在RestTemplate 和Ribbon 作为服务消费者时使用Hys衍ix 。
口 如何在Feign 作为服务消费者时使用Hystrix 。
口 如何使用Hystrix Dashboard 监控熔断器的状况。
口 如何使用Turbine 聚合多个Hystrix Dash board 。

2. 什么是Hystrix:

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

3. Hystrix解决了什么问题:

在复杂的分布式系统中,可能有几十个服务相互依赖,这些服务由于某些原因,例如机房的不可靠性、网络服务商的不可靠性等,导致某个服务不可用。
如果系统不隔离该不可用的服务,可能会导致整个系统不可用。

例如,对于依赖30 个服务的应用程序,每个服务的正常运行时间为99.99% ,对于单个服务来说, 99.99% 的可用是非常完美的。
有99.9930 = 99.7% 的可正常运行时间和0.3% 的不可用时间,那么10 亿次请求中有3000000次失败,实际的情况可能比这更糟糕。

如果不设计整个系统的韧性,即使所有依赖关系表现良好,单个服务只有0.01% 的不可用,由于整个系统的服务相互依赖,最终对整个系统的影响是非常大的。
在微服务系统中, 一个用户请求可能需要调用几个服务才能完成。如图8-1 所示,在所有的服务都处于可用状态时, 一个用户请求需要调用A 、H 、I 和P 服务。
当某一个服务,例如服务I,出现网络延迟或者故障时,即使服务A 、H 和P 可用,由于服务I 的不可用,整个用户请求会处于阻塞状态,并等待服务I 的响应。

在高并发的情况下,单个服务的延迟会导致整个请求都处于延迟状态,可能在几秒钟就使整个服务处于线程负载饱和的状态。
某个服务的单个点的请求故障会导致用户的请求处于阻塞状态,最终的结果就是整个服务的线程资源消耗殆尽。由于服务的依赖性,
会导致依赖于该故障服务的其他服务也处于线程阻塞状态,最终导致这些服务的线程资源消耗殆尽, 直到不可用,从而导致整个问服务系统都不
可用,即雪崩效应。 为了防止雪崩效应,因而产生了熔断器模型。Hystrix 是在业界表现非常好的一个熔断器模型实现的开源组件,它是Spring Cloud 组件不可缺少的一部分。

4. Hystrix的设计原则:

总的来说, Hystrix 的设计原则如下。
口防止单个服务的故障耗尽整个服务的Servlet 容器(例如Tomcat )的线程资源。
口快速失败机制,如果某个服务出现了故障,则调用该服务的请求快速失败,而不是线程等待。
口提供回退( fallback )方案,在请求发生故障时,提供设定好的回退方案。
口使用熔断机制,防止故障扩散到其他服务。
口提供熔断器的监控组件Hystrix Dashboard,可以实时监控熔断器的状态。

5. Hystrix的工作机制:

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

项目演示
在RestTemplate和Ribbon上使用熔断器和feign上使用熔断器

本次工程部分代码参考feign的简单使用

  <modules>
        <module>eureka-client</module>   参考之前的项目
        <module>eureka-server</module> 参考之前的项目
        <module>eureka-ribbon-client</module> 新搭建
		<module>eureka-feign-client</module> 改动代码
    </modules>

一: 编写Eureka Ribbon Client (演示 RestTemplate+Ribbon+Hystrix功能):

1.在POM文件中引入依赖:

        <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-hystrix</artifactId>
        </dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</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>
  1. 配置application.yml
spring:
  application:
    name: eureka-ribbon-client
server:
  port: 8764

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
  1. 在EurekaRibbonClientApplication上增加@EnableEurekaClient开启 Eureka Client的功能,增加@EnableHystrix功能开启Hystrix熔断器功能。
    在日志中看到: DiscoveryClient_EUREKA-CLIENT/localhost:eureka-ribbon-client:8764 - registration status: 204 代表服务注册成功。

  2. 新建一个RibbonConfig加上@Configuration注解,标识此类为配置类。
    在此类中为IoC 容器中注入一个RestTemplate 的Bean , 并在这个Bean 上加上@LoadBalanced 注解,此时RestTemplate 就结合了
    Ribbon 开启了负载均衡功能。

    @Configuration
public class RibbonConfig {

    /**
     * 在此类中为IoC 容器中注入一个RestTemplate 的Bean , 并在这个Bean 上加上@LoadBalanced 注解,此时RestTemplate 就结合了
     * Ribbon 开启了负载均衡功能。
     * @return
     */
    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }
}
  1. 写一个RibbonService类加上@Service注解,在该类的hi()方法用restTemplate调用eureka-client的API接口。
    restTemplate中的Uri不需要使用硬编码(比如IP),只需要写服务名eureka-client即可程序会根据服务名称 eureka-client到本地缓存的注册中心列表去自动获取IP和端口信息。

    在hi()方法上加@HystrixCommand 注解。有了@HystrixCommand注解, hi()方法就启用Hystrix 熔断器的功能,其中, fallbackMethod 为处理回退( fallback )逻辑的方法。
    在熔断器打开的状态下,会执行fall back 逻辑。fall back 的逻辑最好是返回一些静态的字符串,不需要处理复杂的逻辑,也不需要远程调度其他服务,这样方便执行快速失败,释放线程资源。
    如果一定要在fallback 逻辑中远程调度其他服务,最好在远程调度其他服务时,也加上熔断器。

@Service
public class RibbonService {

    @Autowired
    RestTemplate restTemplate;

    /**
     * 在该类的hi()方法用restTemplate调用eureka-client的API接口  Uri 上不需要使用硬编码(比如IP),只需要写服务名eureka-client即可
     * 程序会根据服务名称 eureka-client到Eureka-server注册中心去自动获取IP和端口信息。
     *
     *
     * 在hi()方法上加@HystrixCommand 注解。有了@HystrixCommand注解, hi()方法就启用Hystrix 熔断器的功能,
     * 其中, fallbackMethod 为处理回退( fallback )逻辑的方法。
     * @param name
     * @return
     */
    @HystrixCommand(fallbackMethod = "hiError")
    public String hi(String name) {
        return restTemplate.getForObject("http://eureka-client/hi?name="+name,String.class);
    }

    public String hiError (String name){
        return "Hi," + name + ", sorry, error!";
    }
}
  1. 写一个RibbonController类,为该类加上@RestController 注解,开启RestController 的功能,写一个"/hi" Get 方法的接口,调用RibbonService 类的hi()方法。
@RestController
public class RibbonController {

    /**
     * 写一个"/hi" Get 方法的接口,调用RibbonService 类的hi()方法
     */
    @Autowired
    RibbonService ribbonService;
    @GetMapping("/hi")
    public String hi(@RequestParam(required = false,defaultValue = "forezp") String name){
        return ribbonService.hi(name);
    }
 }
  1. 在浏览器上访问http://localhost:8765/hi?name=forezp, 浏览器会显示如下信息:
    hi forezp,i am from port:8762

  2. 关闭eureka-client服务。

  3. 在浏览器上访问http://localhost:8765/hi?name=forezp, 浏览器会显示如下信息:
    Hi,forezp, sorry, error!

    由此可见, 当eureka-client 不可用时,调用eureka-ribbon-client 的“hi"接口会进入RibbonService 类的“/hi”方法中。
    由于eureka-client 没有响应,判定eureka-client 不可用,开启了熔断器, 最后进入了fallbackMethod 的逻辑。
    当熔断器打开了,之后的请求会直接执行fallbackMethod 的逻辑。这样做的好处就是通过快速失败,请求能够得到及时处理,线程不再阻塞。

编写Eureka Feign Client (演示 Feign+Hystrix功能):

yml加入

# Feign 的起步依赖中已经包含Hystrix依赖,所以只要在配置文件中开启Hystrix的功能就可以
feign:
  hystrix:
    enabled: true

feign接口修改,指定fallback 为HiHystrix类

@FeignClient(value = "eureka-client",configuration = FeignConfig.class,fallback = HiHystrix.class)
public interface EurekaClientFeign {

    /**
     * 在EurekaClientFeign 接口内部有一个sayHiFromClientEureka()方法,该方法通过Feign 来调用eureka-client 服务的“/hi”的API 接口
     * @param name
     * @return
     */
    @GetMapping(value = "/hi")
    String sayHiFromClientEureka(@RequestParam(value = "name") String name);
}

HiHystrix需要实现feign接口,并重写方法处理熔断逻辑

@Component
public class HiHystrix implements EurekaClientFeign {
    @Override
    public String sayHiFromClientEureka(String name) {
           return "hi,"+name+",sorry,error!";
    }
}

访问过程
在浏览器上访问http://localhost:8765/hi
浏览器会显示如下内容:
hi forezp,i am from port : 8762

关闭eureka-client服务。

在浏览器上访问http://localhost:8765/hi?name=forezp, 浏览器会显示如下信息:
Hi,forezp, sorry, error!

由此可见, 当eureka-client 不可用时,调用eureka-feign-client 的“hi"接口会进入HiService 类的“/hi”方法中。
由于eureka-client 没有响应,判定eureka-client 不可用,开启了熔断器, 最后进入了fallback 的逻辑处理类即HiHystrix。

在feign中使用Hystrix Dashboard

eureka-feign-client改造
pom文件(feign自带的hystrix不是hystrix的起步依赖)

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

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

<!-- feign 打开 Hystrix Dashboard 必须显示依赖下面3个引用-->
<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>

启动类改造

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
@EnableHystrixDashboard
@EnableHystrix
public class EurekaFeignClientApplication {

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

servlet

@Component
public class HystrixStreamServlet {

    @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:8765/hystrix.stream 地址: (spring boot 2.0以上 Hystrix Dashboard需要注入HystrixMetricsStreamServlet),否则http://localhost:8765/hystrix.stream报404错误
返回 ping:
ping:
或者 data:
ping:
代表访问成功。

浏览器访问http://localhost:8765/hystrix 地址:
在Hystrix DashBoard 输入框中输入: http://localhost:8765/hystrix.stream 地址
在Title中输入: forezp
点击 Monitor Stream 按钮

显示eureka-ribbon-client的Hystrix Dashboard 数据。 具体介绍见: https://github.com/Netflix/Hystrix 官方文档(需要访问接口http://localhost:8765/hi才能出现监控数据)
(一圈,一线,七色)
在这里插入图片描述

使用turbine聚合监控

对eureka-ribbon-client也进行上面的hystrix dashboard改造(代码省略)

新建工程eureka-monitor-client–8769
pom文件

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

	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-netflix-turbine</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-eureka-client</artifactId>
	</dependency>

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

yml

spring:
  application.name: service-turbine
server:
  port: 8769

  # 1. cluster-name-expression指定集群名称,默认表达式appName;此时:turbine.app-config需要配置想要监控的应用名称
  # 2. 当cluster-name-expression: default时,turbine.aggregator.cluster-config可以不写,因为默认就是default
  # 3. 当cluster-name-expression: metadata['cluster']时,假设想要监控的应用配置了eureka.instance.metadata-map.cluster: ABC,则需要配置,同时turbine.aggregator.cluster-config: ABC
turbine:
  combine-host-port: true  #表示用host主机名和端口来区分不同服务
  app-config: eureka-ribbon-client,eureka-feign-client
  cluster-name-expression: new String("default")
  aggregator:
    cluster-config: default
  instanceUrlSuffix: /hystrix.stream # 这里必须设置,否则默认程序会读取/actuator/hystrix.stream


eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

启动类

@SpringBootApplication
@EnableTurbine
@EnableEurekaClient
@EnableHystrixDashboard
public class EurekaMonitorClientApplication {

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

在浏览器上分别访问:
http://localhost:8764/hi?name=eureka-ribbon-client
http://localhost:8765/hi?name=eureka-feign-client

在浏览器访问http://localhost:8764/hystrix/ 进入Hystrix Dashboard界面。 在界面上一次输入监控刘的Url地址:
http://localhost:8769/turbine.stream,监控时间间隔2000毫秒和title, 点击monitor 查看eureka-ribbon-client和eureka-feign-client的Hystrix Dashboard。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值