Spring Cloud Netflix Hystrix

目录

一、 Hystrix 简介

1 什么是灾难性雪崩效应

2 什么是 Hystrix

二、 服务降级

1 修改 application service 代码

 2 application client POM 依赖

3 application client 容错处理代码 

4 application client 配置文件 application.yml 

5 application client 启动类 

三、 服务熔断 

1 application client POM 依赖

2 application client 容错处理代码 

 3 application client 配置文件 application.yml

4 application client 启动类  

四、 请求缓存  

1 修改 application service 代码

2 application client POM 依赖 

3 application client 容错处理代码 

4 application client 配置文件 application.yml  

5 application client 启动类  

五、 Openfeign 的雪崩处理 

1 服务降级

1.1 POM 依赖

1.2 application client 接口

1.3 application client 接口实现

1.4 application client 配置文件 application.yml 

1.5 applicaiton client 启动类 

2 服务熔断  

六、 可视化的数据监控 Hystrix-dashboard 

1 POM 依赖

2 配置文件 application.yml

3 启动类 

4 访问 Hystrix 监控数据 


一、 Hystrix 简介

1 什么是灾难性雪崩效应

Spring Cloud Netflix Hystrix_第1张图片

Spring Cloud Netflix Hystrix_第2张图片 

造成灾难性雪崩效应的原因,可以简单归结为下述三种:
服务提供者不可用。如:硬件故障、程序 BUG 、缓存击穿、并发请求量过大等。
重试加大流量。如:用户重试、代码重试逻辑等。
服务调用者不可用。如:同步请求阻塞造成的资源耗尽等。
雪崩效应最终的结果就是:服务链条中的某一个服务不可用,导致一系列的服务不可
用,最终造成服务逻辑崩溃。这种问题造成的后果,往往是无法预料的。
解决灾难性雪崩效应的方式通常有:降级、熔断和请求缓存。

2 什么是 Hystrix

Hystrix [hɪst'rɪks] ,中文含义是豪猪,因其背上长满棘刺,从而拥有了自我保护的能力。
本文所说的 Hystrix Netflix 开源的一款容错框架,同样具有自我保护能力。为了实现容
错和自我保护,下面我们看看 Hystrix 如何设计和实现的。
Hystrix 设计目标:
1 、 对来自依赖的延迟和故障进行防护和控制——这些依赖通常都是通过网络访问的
2 、 阻止故障的连锁反应
3 、 快速失败并迅速恢复
4 、 回退并优雅降级
5 、 提供近实时的监控与告警
Hystrix 遵循的设计原则:
1 、 防止任何单独的依赖耗尽资源(线程)
2 、 过载立即切断并快速失败,防止排队
3 、 尽可能提供回退以保护用户免受故障
4 、 使用隔离技术(例如隔板,泳道和断路器模式)来限制任何一个依赖的影响
5 、 通过近实时的指标,监控和告警,确保故障被及时发现
6 、 通过动态修改配置属性,确保故障及时恢复
7 、 防止整个依赖客户端执行失败,而不仅仅是网络通信
Hystrix 如何实现这些设计目标?
1 、 使用命令模式将所有对外部服务(或依赖关系)的调用包装在 HystrixCommand
HystrixObservableCommand 对象中,并将该对象放在单独的线程中执行;
2 、 每个依赖都维护着一个线程池(或信号量),线程池被耗尽则拒绝请求(而不是
让请求排队)。
3 、 记录请求成功,失败,超时和线程拒绝。
4 、 服务错误百分比超过了阈值,熔断器开关自动打开,一段时间内停止对该服务的
所有请求。
5 、 请求失败,被拒绝,超时或熔断时执行降级逻辑。
6 、 近实时地监控指标和配置的修改。
Spring cloud 中处理服务雪崩效应,都需要依赖 hystrix 组件。在 Application Client
应用的 pom 文件中都需要引入下述依赖:
Spring Cloud Netflix Hystrix_第3张图片

 

二、 服务降级

降级是指,当请求超时、资源不足等情况发生时进行服务降级处理,不调用真实服务
逻辑,而是使用快速失败( fallback )方式直接返回一个托底数据,保证服务链条的完整,
避免服务雪崩。
解决服务雪崩效应,都是避免 application client 请求 application service 时,出现服务
调用错误或网络问题。处理手法都是在 application client 中实现。我们需要在 application
client 相 关 工 程 中 导 入 hystrix 依 赖 信 息 。 并 在 对 应 的 启 动 类 上 增 加 新 的 注 解
@EnableCircuitBreaker, 这个注解是用于开启 hystrix 熔断器的,简言之,就是让代码中的
hystrix 相关注解生效。
具体实现过程如下:

1 修改 application service 代码

修改 application service 工程中的代码,模拟超时错误。此模拟中,让服务端代码返回
之前休眠 2000 毫秒,替代具体的复杂服务逻辑。
@RestController
public class ServiceController {
@GetMapping
public Object first(){
try {
// 用于模拟远程服务调用延时。
Thread. sleep ( 2000 );
} catch (InterruptedException e) {
e.printStackTrace();
}
return "测试 Spring Cloud Netflix Ribbon 开发服务提供者" ;
}
}

 2 application client POM 依赖

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

3 application client 容错处理代码 

@Service
public class ClientServiceImpl implements ClientService {
@Autowired
private LoadBalancerClient
loadBalancerClient ;
/**
* @HystrixCommand - 开启 Hystrix 容错处理的注解。代表当前方法如果出现服务
调用问题,使用 Hystrix 容错处理逻辑来处理 *
属性 fallbackMethod - 如果当前方法调用服务,远程服务出现问题的时候,调
用本地的哪个方法得到托底数据。
*/
@HystrixCommand(fallbackMethod = "downgradeFallback" )
@Override
public String first() {
ServiceInstance si = this . loadBalancerClient .choose( "application-service" );
StringBuilder sb = new StringBuilder();
sb.append( "http://" ).append(si.getHost())
.append( ":" ).append(si.getPort()).append( "/" );
System. out .println( "本次访问的 service 是: " + sb.toString());
RestTemplate rt = new RestTemplate();
ParameterizedTypeReference type = new ParameterizedTypeReference(){};
ResponseEntity response =
rt.exchange(sb.toString(), HttpMethod. GET , null , type);
String
result = response.getBody();
return
result;
}
// 本地容错方法,只有远程服务调用过程出现问题的时候,才会调用此方法,获取
托底数据。保证服务完整性。
private String downgradeFallback(){
return "服务降级方法返回托底数据" ;
}
}

4 application client 配置文件 application.yml 

Spring Cloud Netflix Hystrix_第4张图片

5 application client 启动类 

Spring Cloud Netflix Hystrix_第5张图片

三、 服务熔断 

当一定时间内,异常请求比例(请求超时、网络故障、服务异常等)达到阀值时,启 动熔断器,熔断器一旦启动,则会停止调用具体服务逻辑,通过 fallback 快速返回托底数
据,保证服务链的完整。
熔断有自动恢复机制,如:当熔断器启动后,每隔 5 秒,尝试将新的请求发送给服务
提供者,如果服务可正常执行并返回结果,则关闭熔断器,服务恢复。如果仍旧调用失败,
则继续返回托底数据,熔断器持续开启状态。
Spring Cloud Netflix Hystrix_第6张图片
具体实现过程如下:

1 application client POM 依赖

Spring Cloud Netflix Hystrix_第7张图片

2 application client 容错处理代码 

@Service
public class ClientServiceImpl
implements ClientService {
@Autowired
private LoadBalancerClient
loadBalancerClient ;
/**
* @HystrixCommand - 开启 Hystrix 容错处理的注解。代表当前方法如果出现服务
调用问题,使用 Hystrix 容错处理逻辑来处理
*
属性 fallbackMethod - 如果当前方法调用服务,远程服务出现问题的时候,调
用本地的哪个方法得到托底数据。
*/
@HystrixCommand (fallbackMethod = "downgradeFallback" ,
commandProperties = {
// 默认 20 个;10s 内请求数大于 20 个时就启动熔断器,当请求符合熔断条 件时将触发 fallback 逻辑
@HystrixProperty(name =
HystrixPropertiesManager. CIRCUIT_BREAKER_REQUEST_VOLUME_THRESHOLD , value = "10" ),
// 请求错误率大于 50%时就熔断,然后 for 循环发起请求,当请求符合熔断
条件时将触发
@HystrixProperty(name =
HystrixPropertiesManager. CIRCUIT_BREAKER_ERROR_THRESHOLD_PERCENTAGE , value = "50" ),
// 默认 5 秒;熔断多少秒后去尝试请求
@HystrixProperty(name =
HystrixPropertiesManager. CIRCUIT_BREAKER_SLEEP_WINDOW_IN_MILLISECONDS , value =
"5000" )
}
)
@Override
public String first() {
ServiceInstance si =
this . loadBalancerClient .choose( "application-service" );
StringBuilder sb = new StringBuilder();
sb.append( "http://" ).append(si.getHost())
.append( ":" ).append(si.getPort()).append( "/" );
System. out .println( "本次访问的 service 是: " + sb.toString());
RestTemplate rt = new RestTemplate();
ParameterizedTypeReference type =
new ParameterizedTypeReference() {
};
ResponseEntity response =
rt.exchange(sb.toString(), HttpMethod. GET , null , type);
String
result = response.getBody();
return
result;
}
// 本地容错方法,只有远程服务调用过程出现问题的时候,才会调用此方法,获取
托底数据。保证服务完整性。
private String downgradeFallback(){
return "服务降级方法返回托底数据" ;
}

 3 application client 配置文件 application.yml

Spring Cloud Netflix Hystrix_第8张图片

4 application client 启动类  

Spring Cloud Netflix Hystrix_第9张图片

四、 请求缓存  

请求缓存:通常意义上说,就是将同样的 GET 请求结果缓存起来,使用缓存机制(如
redis mongodb )提升请求响应效率。
使用请求缓存时,需要注意非幂等性操作对缓存数据的影响。
请求缓存是依托某一缓存服务来实现的。在案例中使用 redis 作为缓存服务器,那么
可以使用 spring-data-redis 来实现 redis 的访问操作。

1 修改 application service 代码

@RestController
public class ServiceController {
@PostMapping ( "/testPost" )
public Object testPost(){
System. out .println( "testPost method run" );
return "写操作返回" ;
}
@GetMapping ( "/testGet" )
public Object testGet(){
System. out .println( "testGet method run" );
return "读操作返回" ;
}
@GetMapping
public Object first(){
System. out .println( "run" );
try {
// 用于模拟远程服务调用延时。 Thread. sleep ( 2000 );
} catch (InterruptedException e) {
e.printStackTrace();
}
return "测试 Spring Cloud Netflix Ribbon 开发服务提供者" ;
}
}

2 application client POM 依赖 

Spring Cloud Netflix Hystrix_第10张图片

3 application client 容错处理代码 

/**
*
在类上,增加@CacheConfig 注解,用来描述当前类型可能使用 cache 缓存。
*
如果使用缓存,则缓存数据的 key 的前缀是 cacheNames。
*
cacheNames 是用来定义一个缓存集的前缀命名的,相当于分组。
*/
@CacheConfig(cacheNames = "test.hystrix.caches" )
@Service
public class ClientServiceImpl implements ClientService {
@Autowired
private LoadBalancerClient loadBalancerClient ;
/**
* @HystrixCommand - 开启 Hystrix 容错处理的注解。代表当前方法如果出现服
务调用问题,使用 Hystrix 容错处理逻辑来处理
*
属性 fallbackMethod - 如果当前方法调用服务,远程服务出现问题的时候,
调用本地的哪个方法得到托底数据。
*/
@HystrixCommand (fallbackMethod = "downgradeFallback" ,
commandProperties = {
// 默认 20 个;10s 内请求数大于 20 个时就启动熔断器,当请求符合熔断
条件时将触发 fallback 逻辑 @HystrixProperty (name =
HystrixPropertiesManager. CIRCUIT_BREAKER_REQUEST_VOLUME_THRESHOLD , value = "10" ),
// 请求错误率大于 50%时就熔断,然后 for 循环发起请求,当请求符合熔
断条件时将触发
@HystrixProperty (name =
HystrixPropertiesManager. CIRCUIT_BREAKER_ERROR_THRESHOLD_PERCENTAGE , value = "50" ),
// 默认 5 秒;熔断多少秒后去尝试请求
@HystrixProperty (name =
HystrixPropertiesManager. CIRCUIT_BREAKER_SLEEP_WINDOW_IN_MILLISECONDS ,
value = "5000" )
}
)
@Override
public String first() {
ServiceInstance si = this . loadBalancerClient .choose( "application-service" );
StringBuilder sb = new StringBuilder();
sb.append( "http://" ).append(si.getHost())
.append( ":" ).append(si.getPort()).append( "/" );
System. out .println( "本次访问的 service 是: " + sb.toString());
RestTemplate rt = new RestTemplate();
ParameterizedTypeReference type =
new ParameterizedTypeReference() {};
ResponseEntity response =
rt.exchange(sb.toString(), HttpMethod. GET , null , type);
String
result = response.getBody();
return result;
}
/**
*
@Cacheable - 将当期方法的返回值缓存到 cache 中。
*
只要方法增加了@Cacheable 注解,每次调用当前方法的时候,spring cloud
都会先访问 cache 获取数据,
*
如果 cache 中没有数据,则访问远程服务获取数据。远程服务返回数据,先保
存在 cache 中,再返回给客户端。
*
如果 cache 中有数据,则直接返回 cache 中的数据,不会访问远程服务。 *
请求缓存会有缓存数据不一致的可能。缓存数据过期、失效、脏数据等情况。
*
一旦使用了请求缓存来处理幂等性请求操作。则在非幂等性请求操作中必须管
理缓存。避免缓存数据的错误。
* @return
*/
@Override
@Cacheable( "myCache" )
public String testGet() {
ServiceInstance si = this . loadBalancerClient .choose( "application-service" );
StringBuilder sb = new StringBuilder();
sb.append( "http://" ).append(si.getHost())
.append( ":" ).append(si.getPort()).append( "/testGet" );
System. out .println( "本次访问的 service 是: " + sb.toString());
RestTemplate rt = new RestTemplate();
ParameterizedTypeReference type =
new ParameterizedTypeReference() { };
ResponseEntity response =
rt.exchange(sb.toString(), HttpMethod. GET , null , type);
String result = response.getBody();
return
result;
}
/**
*
@CacheEvict - 管理缓存。根据参数 key 删除缓存中对应的缓存数据。
*
@return
*/
@Override
@CacheEvict( "myCache" )
public String testPost() {
ServiceInstance si = this . loadBalancerClient .choose( "application-service" );
StringBuilder sb = new StringBuilder();
sb.append( "http://" ).append(si.getHost())
.append( ":" ).append(si.getPort()).append( "/testPost" );
System. out .println( "本次访问的 service 是: " + sb.toString()); RestTemplate rt = new RestTemplate();
ParameterizedTypeReference type =
new ParameterizedTypeReference() {
};
ResponseEntity response =
rt.exchange(sb.toString(), HttpMethod. POST , null , type);
String result = response.getBody();
return result;
}
// 本地容错方法,只有远程服务调用过程出现问题的时候,才会调用此方法,获
取托底数据。保证服务完整性。
private String downgradeFallback(){
return "服务降级方法返回托底数据" ;
}
}

4 application client 配置文件 application.yml  

Spring Cloud Netflix Hystrix_第11张图片

5 application client 启动类  

Spring Cloud Netflix Hystrix_第12张图片

五、 Openfeign 的雪崩处理 

在声明式远程服务调用 Openfeign 中,实现服务灾难性雪崩效应处理也是通过 Hystrix
实现的。而 feign 启动器 spring-cloud-starter-openfeign 中是包含 Hystrix 相关依赖的。如果
只使用服务降级功能则不需要做独立依赖。如果需要使用 Hystrix 其他服务容错能力,需
要依赖 spring-cloud-starter-netflix-hystrix 资源 。从 Dalston 版本后,feign 默认关闭 Hystrix
支持。所以必须在全局配置文件中开启 feign 技术中的 Hystrix 支持 。具体实现如下:

1 服务降级

1.1 POM 依赖

Openfeign 的启动器依赖 spring-cloud-starter-openfeign 中,自带 Hystrix 处理相关依赖,
所以不需要修改 POM 依赖,直接通过配置即可开启容错处理机制。

1.2 application client 接口

/**
* 注解属性 fallback - 当前接口远程调用服务发生问题时,使用哪一个对象中的对应方
法用于实现容错逻辑。
*
Openfeign 技术中,容错处理是使用当前接口的实现类实现的。
*
实现类中的方法实现,就是对应的容错 fallback 处理逻辑。
*/
@FeignClient (name= "openfeign-service" , fallback =
FirstClientServiceImpl. class )
public interface FirstClientService extends FirstServiceAPI {
}

1.3 application client 接口实现

/**
*
当前类型的实例必须由 Spring 容器管理,需要使用@Component 注解描述。
*
每个实现方法对应远程服务调用的容错处理逻辑。
*/ @Component
public class FirstClientServiceImpl implements FirstClientService {
@Override
public List testFeign()
{
return Arrays. asList ( "Openfeign 返回托底数据" );
}
@Override
public User getMultiParams(Integer id, String name) {
User user = new User();
user.setId( 0 );
user.setUsername( "托底数据" );
user.setRemark( "getMultiParams" );
return user;
}
@Override
public User postMultiParams(Integer id, String name) {
User user = new User();
user.setId( 0 );
user.setUsername( "托底数据" );
user.setRemark( "postMultiParams" );
return user;
}
@Override
public User postObjectParam(User pojo) {
User user = new User();
user.setId( 0 );
user.setUsername( "托底数据" );
user.setRemark( "postObjectParam" );
return user;
}
}

1.4 application client 配置文件 application.yml 

Spring Cloud Netflix Hystrix_第13张图片

1.5 applicaiton client 启动类 

Spring Cloud Netflix Hystrix_第14张图片

2 服务熔断  

Openfeign 技术中,服务熔断对代码和依赖没有其他任何要求,只需要增加对应的
配置即可,具体配置如下:
Spring Cloud Netflix Hystrix_第15张图片

六、 可视化的数据监控 Hystrix-dashboard 

Hystrix Dashboard 是一款针对 Hystrix 进行实时监控的工具,通过 Hystrix Dashboard
我们可以在直观地看到各 Hystrix Command 的请求响应时间 , 请求成功率等数据。
具体开启方式如下:

1 POM 依赖

Hystrix Dashboard 是针对 Hystrix 容错处理相关数据的监控工具。只要在使用了 Hystrix
技术的应用工程中导入对应依赖即可。注意:如果在 Openfeign 技术中开启 Hystrix
Dashboard 监控,则需要将 spring-cloud-starter-netflix-hystrix 启动器导入 POM 文件,否则
无法在启动类上使用 @EnableCircuitBreaker 注解。
Spring Cloud Netflix Hystrix_第16张图片

2 配置文件 application.yml

Spring Cloud Netflix Hystrix_第17张图片

Spring Cloud Netflix Hystrix_第18张图片 

3 启动类 

Spring Cloud Netflix Hystrix_第19张图片

4 访问 Hystrix 监控数据 

通过浏览器访问提供监控访问路径的应用,具体地址为:
http://ip:port/actuator/hystrix.stream
得到的监控结果如下
Spring Cloud Netflix Hystrix_第20张图片
这种监控数据的获取都是 JSON 数据。且数据量级较大。不易于查看。可以使用 Hystrix
Dashboard 提供的视图界面来观察监控结果。视图界面访问路径为: http://ip:port/hystrix
Spring Cloud Netflix Hystrix_第21张图片

进入后的监控视图界面具体含义如下:

Spring Cloud Netflix Hystrix_第22张图片 

 

 

 

你可能感兴趣的:(Hystrix,spring,cloud)