Hystrix的原理及使用

在真正学习Hystrix之前,让我们愉悦的谈谈Hystrix产生的背景

一、背景介绍
1、服务雪崩
分布式系统环境下,服务间类似依赖非常常见,一个业务调用通常依赖多个基础服务。如下图,

如果各个服务正常运行,那大家齐乐融融,高高兴兴的,但是如果其中一个服务崩坏掉会出现什么样的情况呢?如下图,

当Service A的流量波动很大,流量经常会突然性增加!那么在这种情况下,就算Service A能扛得住请求,Service B和Service C未必能扛得住这突发的请求。
此时,如果Service C因为抗不住请求,变得不可用。那么Service B的请求也会阻塞,慢慢耗尽Service B的线程资源,Service B就会变得不可用。紧接着,Service A也会不可用。

So,简单地讲。一个服务失败,导致整条链路的服务都失败的情形,我们称之为服务雪崩。

2、引起雪崩的原因和服务雪崩的三个阶段
原因大致有四:
1、硬件故障;
2、程序Bug;
3、缓存击穿(用户大量访问缓存中没有的键值,导致大量请求查询数据库,使数据库压力过大);
4、用户大量请求;

服务雪崩的第一阶段: 服务不可用;
第二阶段:调用端重试加大流量(用户重试/代码逻辑重试);
第三阶段:服务调用者不可用(同步等待造成的资源耗尽);

3、解决方案
1) 应用扩容(扩大服务器承受力)

加机器
升级硬件
2)流量控制(超出限定流量,返回类似重试页面让用户稍后再试)

限流
关闭重试
3) 缓存

将用户可能访问的数据大量的放入缓存中,减少访问数据库的请求。

4)服务降级

服务接口拒绝服务
页面拒绝服务
延迟持久化
随机拒绝服务
5) 服务熔断

如果对服务降级和服务熔断的概念模糊点此了解 关于服务熔断和服务降级的详解

二、Hystrix入门
Hystrix简介
Hystrix [hɪst’rɪks],中文含义是豪猪,因其背上长满棘刺,从而拥有了自我保护的能力。

以项目案例开始,快速入门(使用IDEA)
场景假设1( 服务提供方报错) : 在服务提供端中因为访问不到数据库中的数据(比如数据不存在,或是数据库压力过大,查询请求队列中),在这种情况下,服务提供方这边如何实现服务降级,以防止服务雪崩.

使用IDEA新建一个 microservice-provider-hystrix 工程
因为此工程要受到Hystrix保护,所以加入依赖.
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
1
2
3
4
在microservice-provider-hystrix 工程的启动类上启用断路器
在启动类上加入注解
@EnableCircuitBreaker //启用断路器
注意: 这里其实也可以使用 spring cloud应用中的@SpringCloudApplication注解,因为它已经自带了这些注解,源码如下:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public @interface SpringCloudApplication {

}
1
2
3
4
5
6
7
8
9
10
在 ProductController中加入断路逻辑
@RequestMapping("/get/{id}")
@HystrixCommand(fallbackMethod="errorCallBack") //模仿没有这个数据时,服务降级
public Object get(@PathVariable("id") long id){
Product p=this.productService.findById(id);
if( p==null){
throw new RuntimeException("查无此产品");
}
return p;
}

//指定一个降级的方法
public Object errorCallBack( @PathVariable("id") long id ){
return id+"不存在,error";
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
启动provider服务后测试

小结: 服务降级 由服务提供方 处理

场景假设2: 因为网络抖动,或服务端维护导致的服务暂时不可用,此时是客户端联接不到服务器,因为feign有重试机制,这样会导致系统长时间不响应,那么在这种情况上如何通过 feign+hystrix 在服务的消费方实现服务熔断(回退机制)呢?

首先确认一下我们使用的客户端是 microservice-consumer-feign , feign中自带了 hystrix,但并没有启动,所以要配置启用hystrix,修改 application.yml

feign:
hystrix:
enabled: true
1
2
3
我们的服务消费方的feign操作接口位于 microservice-interface中,所以要在这里配置

建立一个包 fallback,用于存回退处理类 IProductClientServiceFallbackFactory,这个类有出现请求异常时的处理
package com.yc.springcloud2.fallback;

import com.yc.springcloud2.bean.Product;
import com.yc.springcloud2.service.IProductClientService;
import feign.hystrix.FallbackFactory;

import java.util.List;
@Component //必须被spring 托管
public class IProductClientServiceFallbackFactory implements FallbackFactory<IProductClientService> {
@Override
public IProductClientService create(Throwable throwable) {
//这里提供请求方法出问题时回退处理机制
return new IProductClientService(){

@Override
public Product getProduct(long id) {
Product p=new Product();
p.setProductId(999999999L);
p.setProductDesc("error");
return p;
}

@Override
public List<Product> listProduct() {
return null;
}

@Override
public boolean addPorduct(Product product) {
return false;
}
};
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
在业务接口上加入 fallbackFactory属性指定异常处理类
@FeignClient(name="MICROSERVICE-PROVIDER-PRODUCT",
configuration = FeignClientConfig.class,
fallbackFactory = IProductClientServiceFallbackFactory.class) // 配置要按自定义的类FeignClientConfig
public interface IProductClientService {
1
2
3
4
启动 microservice-consumer-feign客户端进行测试, 在测试时,尝试关闭生产端,看它是否回退

小结: 服务熔断在消费端 处理
三、Hystrix技术点
设计目标:

1. 对来自依赖的延迟和故障进行防护和控制——这些依赖通常都是通过网络访问的
2. 阻止故障的连锁反应
3. 快速失败并迅速恢复
4. 回退并优雅降级
5. 提供近实时的监控与告警
1
2
3
4
5
设计原则:

1. 防止任何单独的依赖耗尽资源(线程)
2. 过载立即切断并快速失败,防止排队
3. 尽可能提供回退以保护用户免受故障
4. 使用隔离技术(例如隔板,泳道和断路器模式)来限制任何一个依赖的影响
5. 通过近实时的指标,监控和告警,确保故障被及时发现
6. 通过动态修改配置属性,确保故障及时恢复
7. 防止整个依赖客户端执行失败,而不仅仅是网络通信
1
2
3
4
5
6
7
Hystrix如何实现:

使用命令模式将所有对外部服务(或依赖关系)的调用包装在HystrixCommand或HystrixObservableCommand对象中,并将该对象放在单独的线程中执行;
每个依赖都维护着一个线程池(或信号量),线程池被耗尽则拒绝请求(而不是让请求排队)。
记录请求成功,失败,超时和线程拒绝。
服务错误百分比超过了阈值,熔断器开关自动打开,一段时间内停止对该服务的所有请求。
请求失败,被拒绝,超时或熔断时执行降级逻辑。
近实时地监控指标和配置的修改。
四、服务监控HystrixDashboard的使用
步骤:

新建一个模块【microservice-consumer-hystrix-dashboard】

pom.xml配置
<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>
1
2
3
4
5
6
7
8
application.yml中配置端口
server:
port: 9001
1
2
创建启动类,配置hystrix启动
package com.yc.springcloud2;

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

@SpringBootApplication
@EnableHystrixDashboard
public class HystrixDashboardApp {
public static void main(String[] args) {
SpringApplication.run( HystrixDashboardApp.class,args);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
启动后可通过 http://localhost:9001/hystrix 访问此应用

dashboard有三种监控模式:
默认的集群监控: http://turbine-hostname:port/turbine.stream
指定的集群监控: http://turbine-hostname:port/turbine.stream?cluster=[clusterName]
单体应用的监控: http://hystrix-app:port/actuator/hystrix.stream

页面上面的几个参数局域:
最上面的输入框: 输入上面所说的三种监控方式的地址,用于访问具体的监控信息页面。
Delay: 该参数用来控制服务器上轮询监控信息的延迟时间,默认2000毫秒。
Title: 该参数对应头部标题Hystrix Stream之后的内容,默认会使用具体监控实例的Url。

注意点:
1.前两种监控模式都是对集群的监控,需要整合Turbine才能实现。
2.而单个服务实例的监控,从http://hystrix-app:port/actuator/hystrix.stream连接中可以看出,Hystrix Dashboard监控单节点实例需要访问实例的actuator/hystrix.stream接口,我们自然就需要为服务实例添加这个端点

在 [microservice-provider-hystrix] 中的pom中加入actuator监控模块,以开启监控相关的端点,并确保引入断路器的依赖: spring-cloud-starter-hystrix
<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>
1
2
3
4
5
6
7
8
在 [microservice-provider-hystrix] 中修改 application.yml 文件,加入管理终端配置
management:
endpoints:
web:
exposure:
include: '*'
1
2
3
4
5
需要注意的是在Spring Cloud Finchley 版本以前访问路径是/hystrix.stream,如果是Finchley的话就需要加入上面的配置。因为spring Boot 2.0.x以后的actuator default配置只暴露了info和health2个端点,这里我们把所有端点开放,include: '*'代表开放所有端点

确保在 [microservice-provider-hystrix] 的启动主类中使用@EnableCircuitBreaker 注解,开启断路器功能.
@SpringBootApplication
@EnableEurekaClient //启动eureka客户端
@EnableDiscoveryClient //启用服务发现客户端,以获取当前provider的注册信息
@EnableCircuitBreaker //启用断路器
@SpringCloudApplication
public class ProductApp_hystrix {
public static void main(String[] args) {
SpringApplication.run( ProductApp_hystrix.class,args);
}
}

1
2
3
4
5
6
7
8
9
10
11
浏览器访问http://localhost:8888/actuator/hystrix.stream会看到如下页面,因为监控的实例( 即 【microservice-provider-hystrix]本身还没有调用任何服务,所以监控端点也没记录任何信息


新开一个浏览器tab页,访问下 http://localhost:8888/product/get/1,重新刷新下刚才的页面可以看到已经有数据返回了,说明我们的埋点生效了


从浏览器中的信息可以看出这些信息是刚刚请求微服务时所记录的监控信息,但是直接去看这些信息肯定是不友好的(根本看不懂),所以Hystrix Dashboard就派上用场了

在Hystrix Dashboard中间这个输入框中,填入=服务的监控地址,也就是http://admin:a@localhost:8888/actuator/hystrix.stream,点击Monitor Stream按钮,就会跳转到具体的监控页面

 

多次请求http://localhost:8888/product/get/1,会发现监控页面的数据也在实时的更新

小结:
以上我们可以使用dashboard对单个实例做信息监控,但在分布式系统中,有很多实例要运维和监控,这样要开启多个窗口来监控,所以可以利用turbine和dashboard结合来对集群监控.
————————————————
版权声明:本文为CSDN博主「Weichenghenxing」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_38149225/article/details/109454418

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章