什么是Hystrix,Hystrix如何使用
容错框架Hystrix,SpringCloud将Hystrix整合到Netflix项目中了。它主要用来添加一个延迟的阀值和容错逻辑。来帮助我们控制分布式系统之间的组件交互。
那么什么是延迟阀值呢:就拿下图中的销售模块举例,在销售模块调用会员模块的时候,会给销售模块加上一个延迟,比如说 销售模块在限定的时间内没有接收到会员模块的响应或者有问题,就会触发容错的逻辑。
下面简单的介绍下,什么是Hystrix容错框架
1. Hystrix 能使你的系统在出现依赖服务失效的时候,通过隔离系统所依赖的服务,防止服务级联失败,同时提供失败回退机制,更优雅地应对失效,并使你的系统能更快地从异常中恢复。
2. Hystrix 能做什么?
2.1 防止单个依赖耗尽容器(例如 Tomcat)内所有用户线程
2.2 降低系统负载,对无法及时处理的请求快速失败(fail fast)而不是排队
2.3 提供失败回退,以在必要时让失效对用户透明化
2.4 使用隔离机制(例如『舱壁』/『泳道』模式,熔断器模式等)降低依赖服务对整个系统的影响
2.5 针对系统服务的度量、监控和报警,提供优化以满足近实时性的要求
2.6 在 Hystrix 绝大部分需要动态调整配置并快速部署到所有应用方面,提供优化以满足快速恢复的要求
2.7 能保护应用不受依赖服务的整个执行过程中失败的影响,而不仅仅是网络请求
首先,我们把销售模块看作是服务调用者,把会员模块看作服务提供者。 如果会员模块请求不到数据,连接数据库超时。有些网站就会有那种情况,就是如果是请求超时,也不会给用户一个很好的提示,那么这个时候 用户可不管你出了什么问题,用户就会一直点,一直刷新 这样的话,就会发送很多请求到服务器,销售模块就会积压很多请求,会员模块就会一直等待数据库的超时返回,这样就会导致整个集群都有问题了,服务会被阻塞。
传统的解决方式: 1. 添加超时机制 2. 人肉运维。。。
还有一种,那就是本章内容要讲的:Hystrix 容错框架 |
|
在销售模块调用会员模块的时候,会给销售模块加上一个延迟,比如说 销售模块在限定的时间内没有接收到会员模块的响应或者有问题,就会触发容错的逻辑。 如果销售模块与会员模块多次连接失败,那么Hystrix就会触发它的断路器,将这个节点的销售模块与会员模块的链接全部断掉,所有的请求过来,都会走那个回退逻辑。(回退逻辑属于销售模块中的一部分,并不是一个新的模块) 这样的话,实际上是在保护销售模块,它就不用等待超时响应这样的结果了,就直接的可以返回给客户,告诉客户这里有问题了。这样做就可以减轻整个集群的负担了。 |
首先,创建两个接口后 再将服务跑起来:
@RestController public class MyController {
// 模仿成功返回的接口 @RequestMapping(value="/successHello", method=RequestMethod.GET) public String successHello(){ return "successHello"; }
// 模仿在请求的过程中,出现错误的接口 @RequestMapping(value="/errorHello", method=RequestMethod.GET) public String errorHello() throws Exception { Thread.sleep(10000); return "errorHello"; } }
服务开启之后,我们来创建一个客户端,对接口进行访问:
String url_success = "http://localhost:8080/successHello"; HttpGet httpGet = new HttpGet(url_success); CloseableHttpClient httpClient = HttpClients.createDefault(); HttpResponse httpResponse = httpClient.execute(httpGet); String result = EntityUtils.toString(httpResponse.getEntity()); System.out.println(result);
我们再将url换成:http://localhost:8080/errorHello,再执行一下 看效果:
errorHello也是可以正常的返回,只不过因为设置了线程的睡眠,晚了10秒才返回结果,,,上面说的都不是重点,重点是上面与下面的对比,请继续向下看:
接下来我们创建一个实现命令类:HelloCommand.java 需继承 HystrixCommand 类
public class HelloCommand extends HystrixCommand<String>{ protected HelloCommand() { super(HystrixCommandGroupKey.Factory.asKey("TestGroup")); } @Override protected String run() throws Exception { // String url = "http://localhost:8080/successHello"; String url = "http://localhost:8080/errorHello"; HttpGet httpGet = new HttpGet(url); CloseableHttpClient httpClient = HttpClients.createDefault(); HttpResponse httpResponse = httpClient.execute(httpGet); String result = EntityUtils.toString(httpResponse.getEntity()); return result; } }
再修改一下main方法,注意观察命令类是怎样使用的:
HelloCommand helloCommand = new HelloCommand(); String result = helloCommand.execute(); System.out.println(result);
如果url使用successHello访问,那么就会正常的返回数据,因为这个接口能快速调通,没有出现连接错误等问题:
但是如果使用加了线程睡眠的接口errorHello,结果会是什么样的呢,我们来看一下:
我们可以看到,因连接超时报的错 重点是 no fallback available. 说明了,我们没有配置回退的逻辑,下面我们就加上这个逻辑,需实现 getFallback 方法:
@Override protected String getFallback() { return "No fallback available."; }
好,我们添加完回退逻辑后,再来执行下main方法,看看还会不会报错: