什么是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框架,那么就需要对集群进行改造

 

在销售模块调用会员模块的时候,会给销售模块加上一个延迟,比如说 销售模块在限定的时间内没有接收到会员模块的响应或者有问题,就会触发容错的逻辑。

如果销售模块与会员模块多次连接失败,那么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方法,看看还会不会报错:

 

posted on 2019-01-01 17:54  沛昕的博客  阅读(1006)  评论(0编辑  收藏  举报