美文网首页
使用Hystrix保护服务

使用Hystrix保护服务

作者: whthomas | 来源:发表于2016-11-22 22:04 被阅读552次

    在分布式的环境中,不同的服务之间总是在相互依赖,难免有时候有的服务会开个小差,影响其他服务的正常运行。HystrixNetflix开发的一款可以帮助我们控制服务之间相互影响的库,保证我们在服务运行的过程中保证不会发生大面积的雪崩

    在项目中加入Hystrix

    在Maven的pom.xml中加入:

    <dependency>
        <groupId>com.netflix.hystrix</groupId>
        <artifactId>hystrix-core</artifactId>
        <version>1.5.8</version>
    </dependency>
    

    虽然大名鼎鼎的Spring Cloud社区将Netflix OSS封装成了一组"全家桶"——Spring Cloud Netflix,并且解决了很多问题,但我还是比较喜欢从原生的一套中学习。

    使用Hystrix

    HystrixCommandHystrix的核心类,Hystrix采用了命令模式,我们可以将自己的逻辑封装到每一个对应的命令中,然后针对不同的逻辑做出相对应的反应。

    这里创建一个例子:

    public class CommandThatFailsFast extends HystrixCommand<String> {
    
        private final boolean throwException;
    
        public CommandThatFailsFast(boolean throwException) {
            super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));
            this.throwException = throwException;
        }
    
        /**
         * 这个方法里面封装了正常的逻辑,我们可以传入正常的业务逻辑
         * 
         * @return
         * @throws Exception
         */
        @Override
        protected String run() throws Exception {
    
            // 如果为true,这个方法丢出异常,如果为false就返回字符串
            if (throwException) {
                throw new RuntimeException("failure from CommandThatFailsFast");
            } else {
                return "success";
            }
        }
    
        /**
         * 这个方法中定义了出现异常时, 默认返回的值(相当于服务的降级)。
         * 
         * @return
         */
        @Override
        protected String getFallback() {
            return "default value";
        }
    
    }
    

    在客户端我们实例化一个CommandThatFailsFast对象之后,可以通过execute()方法同步执行run()方法里面的业务。

    CommandThatFailsFast failsFast = new CommandThatFailsFast(false);
    
    String str1 = failsFast.execute();
    

    HystrixCommandrun()方法中,如果抛出异常,getFallback()方法就会在异常发生时,默认返回一些值,我们就可以在这个地方提供服务降级服务。这样可以为上层调用方(consumer)提供响应,避免服务的雪崩

    Hystrix的响应模型

    除此之外,我们可以利用RxJavaObservable对象(Hystrix就是基于RxJava开发的),来对HystrixCommand的相应结果做出不同的反应:

    Observable<String> fWorld = new CommandHelloWorld("World").observe();
    
    fWorld.subscribe(new Observer<String>() {
        
        // 当run()执行完
        @Override
        public void onCompleted() {
            // nothing needed here
            System.out.println("OnComplete: close function");
        }
        
        // 当发生异常的时候
        @Override
        public void onError(Throwable e) {
    
            if (e instanceof HystrixRuntimeException) {
    
                HystrixRuntimeException exception = (HystrixRuntimeException) e;
    
                if (exception.getFailureType() == HystrixRuntimeException.FailureType.BAD_REQUEST_EXCEPTION) {
                    System.out.println("错误的请求");
                } else if (exception.getFailureType() == HystrixRuntimeException.FailureType.TIMEOUT) {
                    System.out.println("超时异常");
                }
    
            }
    
            e.printStackTrace();
        }
        
        // 每当事件进行一步的时候
        @Override
        public void onNext(String v) {
            System.out.println("onNext: " + v);
        }
    
    });
    

    命名空间

    每一个实例化的HystrixCommand对象都会拥有一个默认的名字——他们的类名,如果我们希望自定义这个名称,就需要在构造方法里面,预先设置好:

    public CommandThatFailsFast(boolean throwException) {
        super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"))
        .andCommandKey(HystrixCommandKey.Factory.asKey("HelloWorld"))
        .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("HelloWorldPool")));
        
        this.throwException = throwException;
    }
    

    上面这个例子中,就将这个Command的名字设置成了HelloWorld

    除了设置名称之外,上面的代码里不难发现还设置了一个Command Group。这个Command Group会将同一组中的数据归档,用于数据的展现,告警等等。

    ThreadPool是指为这个Command提供服务的线程池,每一个HystrixCommand都会关联到一个HystrixThreadPool上,默认情况下Command Group的线程池会成为HystrixCommand的选择。 这个线程池为Hystrix提供监控,Metrics推送,缓存等等使用。

    通过Hystrix,我们可以有效地防止在分布式环境中由于某一个服务的崩溃造成整个系统的影响。

    相关文章

      网友评论

          本文标题:使用Hystrix保护服务

          本文链接:https://www.haomeiwen.com/subject/lbsmpttx.html