Spring Cloud Hystrix介绍与使用
Posted 风某人~Wind
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Cloud Hystrix介绍与使用相关的知识,希望对你有一定的参考价值。
Hystrix
Spring Cloud 里的 Hystrix,是一个容错组件。
Hystrix实现了 超时机制和断路器模式。
Hystrix是Netflix开源的一个类库,用于隔离远程系统、服务或者第三方库,防止级联失败,从而提升系统的可用性与容错性。主要有以下几点功能:
1. 为系统提供保护机制。在依赖的服务出现高延迟或失败时,为系统提供保护和控制。
2. 防止雪崩。
3. 包裹请求:使用HystrixCommand(或HystrixObservableCommand)包裹对依赖的调用逻辑,每个命令在独立线程中运行。
4. 跳闸机制:当某服务失败率达到一定的阈值时,Hystrix可以自动跳闸,停止请求该服务一段时间。
5. 资源隔离:Hystrix为每个请求都的依赖都维护了一个小型线程池,如果该线程池已满,发往该依赖的请求就被立即拒绝,而不是排队等候,从而加速失败判定。防止级联失败。
6. 快速失败:Fail Fast。同时能快速恢复。侧重点是:(不去真正的请求服务,发生异常再返回),而是直接失败。
7. 监控:Hystrix可以实时监控运行指标和配置的变化,提供近实时的监控、报警、运维控制。
8. 回退机制:fallback,当请求失败、超时、被拒绝,或当断路器被打开时,执行回退逻辑。回退逻辑我们自定义,提供优雅的服务降级。
9. 自我修复:断路器打开一段时间后,会自动进入“半开”状态,可以进行打开,关闭,半开状态的转换。
前面讲了一堆,晕不晕,相信有些人看了一遍还是没看懂Hystrix是干嘛的。
Hystrix 总的来讲就干几件事,分别是:降级、熔断、限流,隔离。
1. 什么是降级?
你去外面点小姐姐陪玩,你原本想点的是那个200块一个小时的小姐姐,身材美丽,说话又好听,但是呢,别人没空,不接单了。那你也没办法是吧,只能点个20块一个小时的小姐姐凑合凑合,或者你比较专一,我这次不点了,下次再来。这就是降级。就是你原来发起向服务方的请求,连接超时了,没请求通,你还可以向其他服务发起请求,万一还是没成功,那你就可以给请求方 return “客官下次再来!”,然后返回一个比较友好的页面给用户看 。
2. 隔离
你想点的那个小姐姐,你前面还有20个人在排队呢,今天不接单了,直接就拒绝你了。就是说Hystrix会为每个请求都开一个小型线程池,如果该线程满了,则发往该服务的这个请求会被直接拒绝,而不是在继续排队等候,这就是隔离
3. 限流
限流最容易理解了,玩过英雄联盟的人,以前在战斗之夜送皮肤的时候,有些大区登录的时候是不是要排队,这就是限流。
4. 熔断
你去请求一个服务,请求失败,当你请求某个服务的连续失败次数达到阈值的时候,那我就不请求你这个服务了,我和这个服务已经断开连接了。
但是呢,这个服务过会又好了呢,我们是不是还得需要恢复策略,所以Hystrix里面有个半开状态得策略,就是我可能10次里面随机在去请求一次,我试一试,万一成功了呢,这种在Hystrix里面叫自我修复功能。
有些人还不明白,说你这讲的我还是不懂,那咱们直接用代码来解释
我们可以先定义一个计数器,用来定义连续请求失败的次数
int count =0;
try
//在这之前我们先定义一个阈值,如果count连续失败多少次,我们就不请求了
if(count ==10)//当我们连续失败10次得时候,我们就不请求了
//但是我们也不能抛弃他把,所以需要一个自我修复策略
//比如我们用个随机数
Random random = new Random();
//当我们随机数随机到1的时候,我就去请求一下试一试
if(random.nextInt(10)==1)
.......
catch(Exeception e)
//这里是如果报错就+1
count++;
//下面是如果成功,就把count重置,
逻辑大概是这样子的,不过Hystrix里面不是用try catch 做的,他是用代理做的。
这里有一点需要注意,你的Spring cloud 版本不能超过Spring Cloud 2020.0
需要了解的朋友可以看下面文档或者官方文档
Spring Cloud 2020.0发布,移除了Hystrix、Zuul等Netflix组件
不说了,咱们直接上代码
1. 先引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>
2. 然后写一个HystrixTest类
并继承HystrixCommand类,并实现其中的run方法,和getFallback方法,其中run方法是跑逻辑的
run方法执行中报错的时候,才会进入getFallback方法,就相当于try catch 的逻辑
Hystrix 可以脱离spring cloud 独立使用
代码如下:
public class HystrixTest extends HystrixCommand //单机版Hystrix
protected HystrixTest(HystrixCommandGroupKey group)
super(group);
@Override
protected Object run() throws Exception
System.out.println("执行逻辑-相当于try");
int i=100/0;//让它报个错,测试一下
System.out.println("i:"+i);
return "xxoo";
@Override
protected Object getFallback()
System.out.println("备用逻辑-相当于catch");
return "报错了";
public static void main(String[] args)
// HystrixTest hystrixTest = new HystrixTest(HystrixCommandGroupKey.Factory.asKey("ext"));
/**
* execute():以同步阻塞方式执行run()。以demo为例,调用execute()后,
* hystrix先创建一个新线程运行run(),
* 接着调用程序要在execute()调用处一直阻塞着,直到run()运行完成
*/
// System.out.println("result:" + hystrixTest.execute());
/**
* queue():以异步非阻塞方式执行run()。以demo为例,
* 一调用queue()就直接返回一个Future对象,
* 同时hystrix创建一个新线程运行run(),
* 调用程序通过Future.get()拿到run()的返回结果,
* 而Future.get()是阻塞执行的
*/
Future<String> futureResult = new HystrixTest(HystrixCommandGroupKey.Factory.asKey("ext")).queue();
String result = "";
try
result = futureResult.get();
catch (InterruptedException e)
// TODO Auto-generated catch block
e.printStackTrace();
catch (ExecutionException e)
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("程序结果:"+result);
Hystrix整合Resttemplate
我这里是开了三个服务
一个是服务注册中心
一个是服务调用方
一个是服务提供方
在SpringCloud中使用Hystrix,需要在入口文件里加上@EnableCircuitBreaker 注解,
@SpringBootApplication
@EnableCircuitBreaker //使用Hystrix 需要加上这个注解
public class EurekaconsumerApplication
创建一个RestTemplateController
做为服务调用方,用来请求服务提供方
我们在定义一个 getRestTemplate() 方法来里面使用 RestTemplate 去请求服务方的接口
在方法上加上注解 @HystrixCommand(fallbackMethod = “getRestTemplatefallback”) 说明这个方法我Hystrix 罩着了
里面属性 fallbackMethod 对应的名称是方法名,如果当前请求报错,则进入备用方法
其实比较简单的
/**
* @Auther: wan
* @Date: 2021/2/23 16:33
* @Description: com.wan.eurekaconsumer.controller restTemplate接口调用测试
* @version: 1.0
*/
@RestController
public class RestTemplateController
@Autowired
RestTemplate restTemplate;
@GetMapping("/getRestTemplate")
@HystrixCommand(fallbackMethod = "getRestTemplatefallback")
public Object getRestTemplate()
String url ="http://provider/getMap";
//restTemplate.getForObject 和restTemplate.getForEntity 区别就在于返回值不同,一个返回字符串,一个返回一个对象
String respStr = restTemplate.getForObject(url, String.class);
System.out.println("respStr:"+respStr);
return respStr;
private String getRestTemplatefallback()
System.out.println("报错,进入备用方案。");
return "error";
我们在服务提供方,就是 RestTemplate 调用的这个url的服务
我们需要在里面报个错,然后验证 getRestTemplatefallback 方法就可以了
Hystrix 整合 Feign
如果不知道Feign是啥,可以阅读我上一篇文章,如果没搭Feign的可以先去阅读,因为我们下面都是基于 Feign 整合 Hystrix
Feign依赖里面自带了 Hystrix 包,所以把 Feign 搭起来了就不需要在引入依赖了
入口文件也不需要加 @EnableCircuitBreaker 注解,有 @EnableFeignClients 这个Feign的注解也已经够了
- 先创建一个类 UserProviderFallback ,并实现我们开始定义好的 Feign API 接口UserApiService,用来统一接受错误请求的
@Component
public class UserProviderFallback implements UserApiService
//继承UserApiService接口,实现其中的所有方法,所有
@Override
public String getWan() //我这里改一个方法用来测试
return "降级了-getWan";
@Override
public String getWanParams(String name)
return null;
@Override
public String postWan()
return null;
@Override
public String postWanParams(String name)
return null;
我把UserApiService 类给你们贴出来把,其实和以前Spring Mvc 都差不多的
UserApiService 类是用Feign来进行远程调用接口的,调用的是 user-provider 这个服务
如果要Feign要用Hystrix ,则加上属性 fallback = UserProviderFallback.class
类名就是上面我们自己定义的类名
/*
@FeignClient(name = "wanFeign",url = "http://localhost:8003")
如果结合eureka ,在FeignClient 注解中就可以不用写url,直接name指定服务名称就可以直接调用了
*/
@FeignClient(name = "user-provider",fallback = UserProviderFallback.class)
public interface UserApiService
@GetMapping("/getWan")
public String getWan();
@GetMapping("/getWanParams")
public String getWanParams(@RequestParam("name")String name);
@PostMapping("/postWan")
public String postWan();
@PostMapping("/postWanParams")
public String postWanParams(@RequestParam("name")String name);
Controller 类也给你们贴出来
/**
* @Auther: wan
* @Date: 2021/2/24 11:13
* @Description: com.wan.userconsumer.controller -测试 用 open Feign 请求
* @version: 1.0
*/
@RestController
@RequestMapping("/user")
public class MainController
// @Autowired
// UserApiService userApiService;
//通过eureka服务名称请求
@Autowired
UserApiService userApiService;
//服务直连,不通过eureka,直接进行请求
@GetMapping("/getWan")
public String getWan()
return userApiService.getWan();
//通过eureka服务名称请求-
@GetMapping("/getWan2")
public String getWan2()
return userApiService.getWan();
//通过eureka服务名称请求-带参请求
@GetMapping("/getWanParams")
public String getWanParams()
String name="Hi!! wan";
return userApiService.getWanParams(name);
//通过eureka服务名称请求-post无参请求
@GetMapping("/postWan")
public String postWan()
return userApiService.postWan();
//通过eureka服务名称请求-post带参请求
@GetMapping("/postWanParams")
public String postWanParams()
String name="Hi!! wan";
return userApiService.postWanParams(name);
这样我们的服务调用方的代码就写好了,但是我们需要调用服务提供方的接口测试一下吧
服务提供方的 Controller 类
/**
* @Auther: wan
* @Date: 2021/2/24 11:00
* @Description: com.wan.userprovider.controller
* @version: 1.0
*/
@RestController
public class UserController
//无参get方法
@GetMapping("/getWan")
public String getWan() throws InterruptedException
int i=1/0;//在这里让请求报个错
return "Hi wan 调用方式为:get!!";
//带参get方法
@GetMapping("/getWanParams")
public String getWanParams(String name)
return "Hello !! 调用方式为:get ,参数为:"+name;
//无参post方法
@PostMapping("/postWan")
public String postWan()
return "Hi wan 调用方式为:post!!";
//带参post方法
@PostMapping("/postWanParams")
public String postWanParams(String name)
return "Hi wan 调用方式为:post,参数为:"+name;
效果
服务提供方程序里面报错了,但是并没有把错误返回给前端,只是进行服务降级了
好处就是不会把赤裸直接的错误返回给前端页面,当服务出问题的时候,给前端返回一些相对友好的信息,比如返回一些信息页面,让用户稍后在试。
以上是关于Spring Cloud Hystrix介绍与使用的主要内容,如果未能解决你的问题,请参考以下文章
Spring Cloud Hystrix理解与实践:搭建简单监控集群
Spring Cloud实战之初级入门— 利用Hystrix实现服务熔断与服务监控
Spring Cloud 学习——5.使用 feign 的 hystrix 支持
微服务架构之spring cloud hystrix&hystrix dashboard