SpringCloud--浅出Hystrix

1、为什么需要Hystrix

       ①在分布式环境下,服务和服务之间相互调用,无法确保其他服务的可靠性,服务越多可靠性越低,影响当前主流程可靠性。

       ②调用当前流程时因为其他关联服务,如果出现异常、超时等,影响整个应用的可用性,会导致大量服务崩溃。

而hystrix类似电路中的保险丝,及时切断故障的服务(通过一些策略优化调用流程),通过依赖隔离使其不会相互影响。

2、hystrix是什么以及基本用法

hystrix底层大量使用RxJava,事件源(被观察者)observable、订阅者(观察者)subscriber,ObservableDemo的rxjavaDemo是简单的rxjava,了解hystrix必须了解一下RxJava。

其他概念:hot Obserable 局部 cold Observable 完整。

下面有简单三个类 ObservableDemo、HystrixObservableCommandDemo、HystrixCommandDemo通过代码来辅助我们了解hystrix的基本使用。

通过ObservableDemo的180行以下的伪代码,可以大概了解客户端、服务方和hystrix command之间的关系

hystrix command包裹住调用服务方逻辑,客服端通过调用hystrix command来执行,而hystrix command通过各种策略来解决上面的两个主要问题。

command的实现类有HystrixCommand和HystrixObservableCommand ,分别用于返回单个结果和多个结果。

 

 

流程说明:

1:创建一个新的HystrixCommand或者HystrixObservableCommand对象。

2:命令执行,判断以何种方式执行命令

3:是否启用缓存,结果是否被缓存命中,是 返回缓存结果 否 下一步

4:判断熔断器(circuit-breaker)是否打开,如果打开跳到步骤8,进行降级策略

5:判断线程池/队列/信号量是否跑满,如果跑满进入降级步骤8.

6:执行命令HystrixCommand中的run/HystrixObservableCommand中的construct方式(业务逻辑)

6a:依赖逻辑调用超时或者异常,进入步骤8.

7:计算熔断器状态,所有的运行状态(成功, 失败, 拒绝,超时)上报给熔断器,用于统计从而判断熔断器状态.

8:getFallback()降级逻辑.

以下三种情况将触发getFallback调用:

(1):run()或者construct出现异常或超时,非HystrixBadRequestException异常

或者指定忽略的异常

(2):熔断器开启

(3):线程池/队列/信号量是否跑满

8a:没有实现getFallback的Command将直接抛出异常

8aa: execute() 抛出异常

8ab: queue() 调用get()时抛出异常

8ac:observe() 订阅的时候通过onError来通知终止请求

8ad:toObserve() 订阅的时候通过onError通知终止请求

8b:fallback降级逻辑调用成功直接返回

8c:降级逻辑调用失败抛出异常

9:返回执行成功结果Observable

 

package com.zhou.demo.utils;

import rx.Observable;
import rx.Observer;
import rx.Subscriber;
import rx.functions.Action1;

import java.util.Iterator;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

/**
 * @auther: 
 * @description:
 * @date: 10:26 2018/10/31
 */
public class ObservableDemo {

    /**
     *  简单的rxjava demo
     */
    public static void rxjavaDemo(){

        // 创建事件源
        Observable<String> observable = Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {
                subscriber.onNext("hello Rxjava");
                subscriber.onNext("who am i");
                subscriber.onCompleted();
            }
        });

        // 创建订阅者
        Subscriber<String> subscriber = new Subscriber<String>() {
            @Override
            public void onCompleted() {
                System.out.println(" Completed subscriber");
            }

            @Override
            public void onError(Throwable throwable) {
                System.out.println(" error subscriber");
            }

            @Override
            public void onNext(String s) {
                System.out.println("subscriber :" +  s);
            }
        };

        //订阅
        observable.subscribe(subscriber);

    }

    /**
     *  HystrixCommand执行的execute/queue  同步/异步
     *
     *  queue执行的就是toObservable() 返回Future对象
     *  execute是直接通过Future得到结果
     */
    public static void hystrixCommandDemo(String input, int type){
        HystrixCommandDemo command = new HystrixCommandDemo(input);
        String result = null;
        if(type == 1){
            result = command.execute(); // this.queue().get();
        }else if(type == 2){
            Future<String> queue = command.queue(); // this.toObservable().toBlocking().toFuture();
            while (!queue.isDone()){
                System.out.println("Do other things ...");
            }
            try {
                result = queue.get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }else{
            result = testObserve(command, type);
        }
        System.out.println("执行结果:" + result);
    }

    /**
     * 虽然HystrixCommand具备了observe()和toObservable()的功能,但是它的实现有一定的局限性,只能执行一个命令,所以只会有一个结果
     * 而Hystrix还提供了HystrixObservableCommand, 通过它实现的命令可以执行多个command
     *
     */
    public static String testObserve(HystrixCommandDemo command, int type){
        /**
         * 返回的是Hot Observable,不论 "事件源" 是否有"订阅者",都会在创建后对事件进行发布。
         * 所以对于Hot Observable的每一个“订阅者”都有可能从“事件源”的中途开始的,并可能只是看到了整个操作的局部过程
         */

        String result = null;
        if(type == 3){
            Observable<String> observe = command.observe();

            observe.subscribe(new Observer<String>() {
                @Override
                public void onCompleted() {
                    System.out.println("==============onCompleted");
                }

                @Override
                public void onError(Throwable e) {
                    e.printStackTrace();
                }

                @Override
                public void onNext(String s) {
                    System.out.println("=========onNext: " + s);
                }
            });


            observe.subscribe(new Action1<String>() {
                @Override
                public void call(String s) {
                    System.out.println("==================call:" + s);
                }
            });

            result = observe.toBlocking().single();

        }else if(type == 4){
            /**
             *  Cold Observable在没有 “订阅者” 的时候并不会发布事件,而是进行等待,直到有 “订阅者” 之后才发布事件
             *  所以对于Cold Observable的订阅者,它可以保证从一开始看到整个操作的全部过程
             */
            Observable<String> observable = command.toObservable();
            System.out.println("此时的结果:" + result);
            observable.subscribe(new Action1<String>() {
                @Override
                public void call(String s) {
                    System.out.println("==================call:" + s);
                }
            });
            result = observable.toBlocking().single();
        }

        return result;
    }


    public static void hystrixObservableCommandDemo(String input, int type){
        HystrixObservableCommandDemo hystrixObservableCommandDemo = new HystrixObservableCommandDemo(input);
        if(type == 1){
            Observable<String> observe = hystrixObservableCommandDemo.observe();
            Iterator<String> iterator = observe.toBlocking().getIterator();
            while(iterator.hasNext()){
                System.out.println("hystrixObservableCommand observe : " + iterator.next());
            }

        }else if(type == 2){
            Observable<String> observable = hystrixObservableCommandDemo.toObservable();
            Iterator<String> iterator = observable.toBlocking().getIterator();
            while(iterator.hasNext()){
                System.out.println("hystrixObservableCommand toObserve : " + iterator.next());
            }
        }


    }



    public static void main(String[] args) {
        hystrixCommandDemo("呵呵呵哒", 3);
        //hystrixObservableCommandDemo("呵呵呵哒", 4);

    }


}

/**
 *
 *   cloud书中伪代码
 *   描述客户端---调用者---hystrix command之间的调用关系
 *
 */

//接收者/服务方
class Receiver{
    public void action(){

    }
}

//抽象命令
interface Command{
    void execute();
}

//具体命令实现类
class ConcreteCommand implements Command{

    private Receiver receiver;

    public ConcreteCommand(Receiver receiver){
        this.receiver = receiver;
    }

    @Override
    public void execute() {
        this.receiver.action();
    }
}

//客户端调用
class Invoker{

    private Command command;

    public void setCommand(Command command){
        this.command = command;
    }

    public void action(){
        command.execute();
    }
}

class Client{
    public static void main(String[] args) {
        Receiver receiver = new Receiver();
        Command command = new ConcreteCommand(receiver);
        Invoker invoker = new Invoker();
        invoker.setCommand(command);
        invoker.action();
    }
}

 

package com.zhou.demo.utils;

import com.netflix.hystrix.*;

/**
 * @auther:
 * @description:
 * @date: 16:40 2018/11/1
 */
public class HystrixCommandDemo extends HystrixCommand<String> {

    private String input;


    /**
     *   GroupKey:该命令属于哪一个组,可以帮助我们更好的组织命令。
         CommandKey:该命令的名称
         ThreadPoolKey:该命令所属线程池的名称,同样配置的命令会共享同一线程池,若不配置,会默认使用GroupKey作为线程池名称。
         CommandProperties:该命令的一些设置,包括断路器的配置,隔离策略,降级设置,以及一些监控指标等。
         ThreadPoolProerties:关于线程池的配置,包括线程池大小,排队队列的大小等。
     */
    protected HystrixCommandDemo(String input) {
        //设置HystrixCommand的属性
        super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("HystrixCommandDemoGroup"))
                .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("HystrixCommandDemoPool"))
                .andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
                        .withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.THREAD))
                .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter()
                        .withCoreSize(10))
        );
        this.input = input;
    }

    @Override
    protected String run() throws Exception {
        return "接收请求:" + input;
    }

    //服务降级
    @Override
    protected String getFallback() {
        return "exeucute Falled";
    }

}
package com.zhou.demo.utils;

import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixObservableCommand;
import rx.Observable;
import rx.Subscriber;
import rx.schedulers.Schedulers;

/**
 * @auther: 
 * @description:
 * @date: 19:05 2018/11/1
 */
public class HystrixObservableCommandDemo extends HystrixObservableCommand<String> {

    private String input;

    protected HystrixObservableCommandDemo(String input) {
        super(HystrixCommandGroupKey.Factory.asKey("HystrixObservableCommandDemoGroup"));
        this.input = input;
    }

    /**
     *    HystrixObservable通过实现 protected Observable<String> construct() 方法来执行逻辑。
     *      通过 重写 resumeWithFallback方法来实现服务降级
     */
    @Override
    protected Observable construct() {
        return Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {
                try {
                    if(!subscriber.isUnsubscribed()) {
                        subscriber.onNext("Hello world ");
                        //int i = 1 / 0; //模拟异常
                        subscriber.onNext("输入了啥:" + input);
                        subscriber.onCompleted();
                    }
                } catch (Exception e) {
                    subscriber.onError(e);
                }
            }
        }).subscribeOn(Schedulers.io());
    }

    /**
     * 服务降级
     */
    @Override
    protected Observable<String> resumeWithFallback() {
        return Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {
                try {
                    if (!subscriber.isUnsubscribed()) {
                        subscriber.onNext("为什么就到fallback了!");
                        subscriber.onNext("找出异常,找出异常!");
                        subscriber.onCompleted();
                    }
                } catch (Exception e) {
                    subscriber.onError(e);
                }
            }
        }).subscribeOn(Schedulers.io());
    }
}

3、hystrix以及spingCloud

相关架包说明
//org.springframework.cloud:sping-cloud-commons 包含了@SpringCloudApplication @EnableCircuitBreaker、@DiscoveryClient、@LoadBalanced注解等注解
//org.springframework.cloud:spring-cloud-netfix-core 包含@EnableHystrix @FeignClient相关→ribbonFeign相关 ribbon、zuul、metrics、endpoint、archaius、rx(rxJava)
//com.netflix.hystrix:hystrix-core   hystrix 核心包
//com.netflix.hystrix:hystrix-javanica  hystrix辅助包,包含hystrix相关注解,使用hystrix更方便

 

我用的版本是1.5.8

zuul是默认开启hystrix的、@EnableZuulProxy中包含@EnableCircuitBreaker

其他服务需要加上hystrix相关依赖和@EnableCircuitBreaker开启hystrix服务

@SpringCloudApplication包含@SpringBootApplication@EnableDiscoveryClient

@EnableCircuitBreaker三个注解

 

参考:https://github.com/Netflix/Hystrix/wiki

参考:《SpringCloud微服务实战》,电子工业出版社,翟永超

  • 10
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值