概述
Hystrix 熔断器
- 1. Hystrix 介绍
- 1.1 是什么:
- 1.2 Hystrix设计原则:
- 1.3 Hystrix特性
- 2. 图解
- 3. SpringCloud 集成Hystrix
- 3.1 maven依赖
- 3.2 添加注解
- 3.Hystrix的服务熔断
- 4. Hystrix的服务降级
- 5. Hystrix的异常处理
- 5.1 未调用远程服务前发生异常
- 5.2 调用远程服务发生异常
- 5.3 忽略异常
- 5.4 自定义Hystrix的服务异常熔断
- 5.4.1 同步调用
- 5.4.1 异步调用
- 6. Hystrix的仪表盘监控
- 6.1 添加maven依赖
- 6.2 启动类添加注解
- 6.3 配置文件中配置服务端口号
- 6.4 配置要监控的项目
- 6.4.1 首先需要引入Hystrix以及Dashboard的依赖
- 6.4.1 修改需要监控的项目配置
1. Hystrix 介绍
1.1 是什么:
在分布式环境中,许多服务依赖项中的一些必然会失败。Hystrix是一个库,通过添加延迟容忍和容错逻辑,帮助你控制这些分布式服务之间的交互。Hystrix通过隔离服务之间的访问点、停止级联失败和提供回退选项来实现这一点,所有这些都可以提高系统的整体弹性。简单点说:就是当被调用方没有响应,向调用方直接返回一个错误响应即可,而不是长时间的等待,这样避免调用时因为等待而线程一直得不到释放。
1.2 Hystrix设计原则:
- 1.防止单个服务的故障,耗尽整个系统服务的容器(比如tomcat)的线程资源,避免分布式环境里大量级联失败。通过第三方客户端访问(通常是通过网络)依赖服务出现失败、拒绝、超时或短路时执行回退逻辑
- 2.用快速失败代替排队(每个依赖服务维护一个小的线程池或信号量,当线程池满或信号量满,会立即拒绝服务而不会排队等待)和优雅的服务降级;当依赖服务失效后又恢复正常,快速恢复
- 3.提供接近实时的监控和警报,从而能够快速发现故障和修复。监控信息包括请求成功,失败(客户端抛出的异常),超时和线程拒绝。如果访问依赖服务的错误百分比超过阈值,断路器会跳闸,此时服务会在一段时间内停止对特定服务的所有请求
- 4.将所有请求外部系统(或请求依赖服务)封装到HystrixCommand或HystrixObservableCommand对象中,然后这些请求在一个独立的线程中执行。使用隔离技术来限制任何一个依赖的失败对系统的影响。每个依赖服务维护一个小的线程池(或信号量),当线程池满或信号量满,会立即拒绝服务而不会排队等待
1.3 Hystrix特性
- 1.请求熔断: 当Hystrix Command请求后端服务失败数量超过一定比例(默认50%), 断路器会切换到开路状态(Open). 这时所有请求会直接失败而不会发送到后端服务. 断路器保持在开路状态一段时间后(默认5秒), 自动切换到半开路状态(HALF-OPEN). 这时会判断下一次请求的返回情况, 如果请求成功, 断路器切回闭路状态(CLOSED), 否则重新切换到开路状态(OPEN). Hystrix的断路器就像我们家庭电路中的保险丝, 一旦后端服务不可用, 断路器会直接切断请求链, 避免发送大量无效请求影响系统吞吐量, 并且断路器有自我检测并恢复的能力.
- 2.服务降级:Fallback相当于是降级操作. 对于查询操作, 我们可以实现一个fallback方法, 当请求后端服务出现异常的时候, 可以使用fallback方法返回的值. fallback方法的返回值一般是设置的默认值或者来自缓存.告知后面的请求服务不可用了,不要再来了。
- 3.依赖隔离(采用舱壁模式,Docker就是舱壁模式的一种):在Hystrix中, 主要通过线程池来实现资源隔离. 通常在使用的时候我们会根据调用的远程服务划分出多个线程池.比如说,一个服务调用两外两个服务,你如果调用两个服务都用一个线程池,那么如果一个服务卡在哪里,资源没被释放后面的请求又来了,导致后面的请求都卡在哪里等待,导致你依赖的A服务把你卡在哪里,耗尽了资源,也导致了你另外一个B服务也不可用了。这时如果依赖隔离,某一个服务调用A B两个服务,如果这时我有100个线程可用,我给A服务分配50个,给B服务分配50个,这样就算A服务挂了,我的B服务依然可以用。
- 4.请求缓存:比如一个请求过来请求我userId=1的数据,你后面的请求也过来请求同样的数据,这时我不会继续走原来的那条请求链路了,而是把第一次请求缓存过了,把第一次的请求结果返回给后面的请求。
- 5.请求合并:我依赖于某一个服务,我要调用N次,比如说查数据库的时候,我发了N条请求发了N条SQL然后拿到一堆结果,这时候我们可以把多个请求合并成一个请求,发送一个查询多条数据的SQL的请求,这样我们只需查询一次数据库,提升了效率。
2. 图解
以下数据、图来自官方文档:https://cloud.spring.io/spring-cloud-static/spring-cloud-netflix/1.3.5.RELEASE/single/spring-cloud-netflix.html#_circuit_breaker_hystrix_clients
Netfilix创建了一个名为Hystrix的库,实现了熔断器模式。在微服务架构中,它通常有多个服务调用层。
微服务图
Hystrix回退以防止连锁故障
一个底层服务的故障会引发直至用户交互层的连锁故障。在一个设定时长为“metrics.rollingStats.timeInMilliseconds”(默认为十秒)的滚动窗口内,对一个特定服务的请求数大于“circuitBreaker.requestVolumeThreshold”(默认为20个),并且故障率大于“circuitBreaker.errorThresholdPercentage”(默认大于百分之五十)的时候,启用熔断机制以使请求失效。在熔断和报错的情况下,开发者可以启用回退机制。
启用熔断机制能防止连锁故障的情况,给故障服务提供时间以恢复正常。回退操作可以是另一个Hystrix受保护的调用、静态数据或是一个恰当的空值。回退操作可能是成串的,所以第一个回退操作会做一些其他的业务请求,让故障回退到预设的值。
3. SpringCloud 集成Hystrix
3.1 maven依赖
注意:添加maven依赖时,注意查看自己的SpringBoot 项目是什么版本的,因为 ServerPropertiesAutoConfiguration 在SpringBoot 2.x.x 移除了。如果你的SpringBoot 版本是2.x.x版本就不要引入这个依赖
<!--旧版本使用的-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
注意:应该引入以下这个版本。(别问我为什么知道?因为我就引错了。。。启动报错:org.springframework.beans.factory.BeanDefinitionStoreException: Failed to process import candidates for configuration class [com.kinglong.springcloud.ComsumerApplication]; nested exception is java.io.FileNotFoundException: class path resource [org/springframework/boot/autoconfigure/web/ServerPropertiesAutoConfiguration.class] cannot be opened because it does not exist
at org.springframework.context.annotation.ConfigurationClassParser.processImports(ConfigurationClassParser.java:596) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE]。
这个问题看官方文档的话,应该可以避免,见下图:)
<!--正确版本,应该是netflix的-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.1.2.RELEASE</version>
</dependency>
3.2 添加注解
Boot app 样例:
启动类
/**
* @SpringBootApplication
* @EnableEurekaClient//eureka客户端支持
* @EnableCircuitBreaker//开启熔断器
* 这三个注解在SpringCloud里可以合并为一个注解:@SpringCloudApplication,效果等同于这三个注解
*/
@SpringCloudApplication
public class ComsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ComsumerApplication.class, args);
}
}
解释:为什么可以这样呢?进入这个注解@SpringCloudApplication内部看可以看到:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootApplication
@EnableDiscoveryClient //此注解作用和@EnableEurekaClient一样,但是还将可以主持其他服务注册器
@EnableCircuitBreaker
public @interface SpringCloudApplication {
}
3.Hystrix的服务熔断
/**
* web api
*
* @author haojinlong
*/
@RestController
@RequestMapping("/api/webs")
public class WebController {
@Autowired
private RestTemplate restTemplate;
/**
* @HystrixCommand由Netflix contrib library提供,被称作“javanica”
* Spring Cloud会自动将包含该注释的Spring bean封装在连接到Hystrix熔断器的代理中
* 熔断器会计算何时启用或关闭熔断机制,并决定在故障时该做什么。
* 在需要考虑熔断的方法上加上该注解即可,fallbackMethod 为回退时的指定操作方法;
* commandProperties:指定超时熔断时间;
*
* @return
*/
@RequestMapping("/hello")
@HystrixCommand(fallbackMethod = "error",commandProperties = {@HystrixProperty (name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500")})//1.5秒超时
public String hello() {
return restTemplate.getForEntity("http://01-SPRINGCLOUD-SERVICE-PROVIDER/api/hellos/hello", String.class).getBody();
}
/**
* 熔断的回调方法,也就是降级方法
* @return
*/
public String error(){
//访问远程服务失败,处理逻辑写在这里即可
return "error";
}
}
4. Hystrix的服务降级
前文提到过:Fallback相当于是降级操作. 对于查询操作, 我们可以实现一个fallback方法, 当请求后端服务出现异常的时候, 可以使用fallback方法返回的值. fallback方法的返回值一般是设置的默认值或者来自缓存.告知后面的请求服务不可用了,不要再来了。这种做法,虽然不能得到正确的返回结果,但至少保证了服务的可用性,比直接抛出错误或服务不可用要好很多,可以根据业务场景自行选择。
5. Hystrix的异常处理
我们在调用服务提供者时,我们自己也有可能会抛出异常,默认情况下方法抛出了异常会自动进行服务降级,交给服务降级中的方法去处理。当我们自己发生异常后,只需要在服务降级方法中添加一个Throwable类型的参数就能够获取抛出的异常的类型。
5.1 未调用远程服务前发生异常
我们在上文的代码中模拟一个异常
/**
* @HystrixCommand由Netflix contrib library提供,被称作“javanica”
* Spring Cloud会自动将包含该注释的Spring bean封装在连接到Hystrix熔断器的代理中
* 熔断器会计算何时启用或关闭熔断机制,并决定在故障时该做什么。
*
* @return
*/
@RequestMapping("/hello")
@HystrixCommand(fallbackMethod = "error", commandProperties = {@HystrixProperty (name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500")})//1.5秒超时
public String hello() {
int i= 10/0;
return restTemplate.getForEntity("http://01-SPRINGCLOUD-SERVICE-PROVIDER/api/hellos/hello", String.class).getBody();
}
/**
* 熔断的回调方法,也就是降级方法
* @return
*/
public String error(){
//访问远程服务失败,处理逻辑写在这里即可
return "error";
}
测试显示,未调用前发生异常也会触发熔断,调用服务是不会触发的,直接抛出运行时异常,并且可以在降级方法里获取到这个异常。
5.2 调用远程服务发生异常
将某个远程服务加入异常代码。测试显示,效果如上,可以在降级方法里获取到这个异常。
5.3 忽略异常
ignoreExceptions = RuntimeException.class 忽略异常,这样可以避免调用降级方法,根据业务场景选择
/**
* web api
*
* @author haojinlong
*/
@RestController
@RequestMapping("/api/webs")
public class WebController {
@Autowired
private RestTemplate restTemplate;
/**
* @HystrixCommand由Netflix contrib library提供,被称作“javanica”
* Spring Cloud会自动将包含该注释的Spring bean封装在连接到Hystrix熔断器的代理中
* 熔断器会计算何时启用或关闭熔断机制,并决定在故障时该做什么。
* 在需要考虑熔断的方法上加上该注解即可,fallbackMethod 为回退时的指定操作方法;
* commandProperties:指定超时熔断时间;
* ignoreExceptions = RuntimeException.class 忽略异常,这样可以避免调用降级方法,根据业务场景选择
*
* @return
*/
@RequestMapping("/hello")
@HystrixCommand(fallbackMethod = "error",ignoreExceptions = RuntimeException.class, commandProperties = {@HystrixProperty (name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500")})//1.5秒超时
public String hello() {
return restTemplate.getForEntity("http://01-SPRINGCLOUD-SERVICE-PROVIDER/api/hellos/hello", String.class).getBody();
}
/**
* 熔断的回调方法,也就是降级方法
* @return
*/
public String error(){
//访问远程服务失败,处理逻辑写在这里即可
return "error";
}
}
5.4 自定义Hystrix的服务异常熔断
自定义类继承HystrixCommand类来实现自定义的Hystrix的请求,在getFallback方法中调用getExecutionException()方法获取服务抛出异常。
5.4.1 同步调用
/**
* web api
*
* @author haojinlong
*/
@RestController
@RequestMapping("/api/webs")
public class WebController {
@Autowired
private RestTemplate restTemplate;
/**
* com.netflix.hystrix.HystrixCommand用全路径引用类是防止和@HystrixCommand这个注解混淆
* MyHystrixCommand自定义熔断器
* execute()调用是同步调用,会一直等待返回结果
*
* @return
*/
@RequestMapping("/hystrix")
public String hystrix() {
return new MyHystrixCommand(com.netflix.hystrix.HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("")), restTemplate, "http://01-SPRINGCLOUD-SERVICE-PROVIDER/api/hellos/hello").execute();
}
}
5.4.1 异步调用
/**
* web api
*
* @author haojinlong
*/
@RestController
@RequestMapping("/api/webs")
public class WebController {
@Autowired
private RestTemplate restTemplate;
/**
* com.netflix.hystrix.HystrixCommand用全路径引用类是防止和@HystrixCommand这个注解混淆
* MyHystrixCommand自定义熔断器
* execute()调用是同步调用,会一直等待返回结果
*
* @return
*/
@RequestMapping("/hystrix")
public String hystrix() {
Future<String> queue = new MyHystrixCommand(com.netflix.hystrix.HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("")), restTemplate, "http://01-SPRINGCLOUD-SERVICE-PROVIDER/api/hellos/hello").queue();
String data = queue.get(20000, TimeUnit.MILLISECONDS);
return data;
}
}
自定义熔断器
package com.kinglong.springcloud.hystrix;
import com.netflix.hystrix.HystrixCommand;
import org.springframework.web.client.RestTemplate;
/**
* 自定义的Hystrix
*
* @author haojinlong
*/
public class MyHystrixCommand extends HystrixCommand<String> {
private RestTemplate restTemplate;
private String url;
public MyHystrixCommand (Setter setter, RestTemplate restTemplate){
super(setter);
this.restTemplate = restTemplate;
}
public MyHystrixCommand (Setter setter, RestTemplate restTemplate, String url){
super(setter);
this.restTemplate = restTemplate;
this.url = url;
}
@Override
protected String run() throws Exception {
//调用远程的服务
return restTemplate.getForEntity(url, String.class).getBody();
}
/**
* 当远程服务超时、异常、不可用时,调用该方法
*
* @return
*/
@Override
protected String getFallback() {
//实现服务熔断、降级处理
return "error";
}
}
6. Hystrix的仪表盘监控
在微服务架构中为例保证程序的可用性,防止程序出错导致网络阻塞,出现了断路器模型。断路器的状况反应了一个程序的可用性和健壮性,它是一个重要指标。Hystrix Dashboard是作为断路器状态的一个组件,提供了数据监控和友好的图形化界面。通过监控该面板,可以很直观的看到每一个服务请求在短时间内(10s)的请求量,以及成功率,失败率,耗时等信息,可以给后期的系统优化提供依据。
这个服务搭建十分快速,使用SpringBoot搭建三步走即可(我是新建的一个项目)
6.1 添加maven依赖
maven依赖最新版本即可
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
<version>2.1.2.RELEASE</version>
</dependency>
6.2 启动类添加注解
@SpringBootApplication
@EnableHystrixDashboard//打开仪表盘功能
public class DashBoardApplication {
public static void main(String[] args) {
SpringApplication.run(DashBoardApplication.class, args);
}
}
6.3 配置文件中配置服务端口号
server.port=3721
大功告成,然后起服即可(访问路径为:http://localhost:3721/hystrix ,记得加上 /hystrix 路径),页面如下图所示:
6.4 配置要监控的项目
6.4.1 首先需要引入Hystrix以及Dashboard的依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.1.2.RELEASE</version>
</dependency>
<!--springboot提供的一个健康检查监控的依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
6.4.1 修改需要监控的项目配置
#用来暴露endpoints的,由于endpoints包含很多敏感信息,除了health、info两个支持直接访问外,其他的默认不支持直接访问,可以指定某个端点访问,如下
#management.endpoints.web.exposure.include=hystrix.stream
#现在做测试,所以用通配符,可以访问所有端点
management.endpoints.web.exposure.include=*
至此,就配置好了
剩下的就是在先前的web页面里添加这个路径即可:http://localhost:8081/actuator/hystrix.stream
配置后,点击监控即可。
最后
以上就是受伤枕头为你收集整理的SpringCloud(Hystrix)的全部内容,希望文章能够帮你解决SpringCloud(Hystrix)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复