Spring Cloud_16_Hystrix的使用(一)

Hystrix的使用(一)

  • 将业务逻辑封装在命令中,交给Hystrix去执行,Hystrix则会帮我们保护程序
  • 命令如何执行?
  • 其中有什么配置?
  • 回退有什么相关配置?

1、内部流程

  • 从之前的例子看,当服务器出现无响应现象的时候,Hystrix会自动使用容错机制,看似简单,其实有一套较为复杂的执行逻辑

  • 第一步:在命令开始执行时,会做一些准备工作(如:为命令创建相应的线程池等)
  • 第二步:判断是否打开了缓存,打开了缓存就直接查找缓存并返回结果
  • 第三步:判断断路器是否打开,如果打开了,就表示链路不可以用,直接执行回退方法
  • 第四步:判断线程池、信号量等条件(如:线程池超负荷,则返回回退方法,否则,就去执行命令的内容)
  • 第五步:执行命令,判断是否要对断路器进行处理,执行完成后,如果满足一定条件,则需要开启断路器
  • 整个流程最主要的点,就是在于断路器是否被打开

2、命令执行

  • toObservable:返回一个最原始的可观察的实例,是一个RxJava的类,执行这个对象可观察命令的执行过程,并且将执行的信息转递给订阅者(命令不会马上执行,只有当返回的可观察实例被订阅之后,才会真正执行)
  • observe:调用toObservable获得最原始的可观察实例后,再使用一个replay subject作为原始toObservable的订阅者(会立刻执行)
  • queue
  • execute:调用queue的get方法,同步
  • 回顾
HttpResponse response = httpClient.execute(httpGet);
  1. 底层使用RxJava执行命令
  2. 执行的时候返回一个可观察的实例
  3. 这样,就可以监控命令的执行,execute是最基础的命令执行方法
package com.atm.cloud;

import rx.Observable;
import rx.Observer;

import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;

public class CommandRunMain {

    public static void main(String[] args) throws Exception {
        RunCommand c1 = new RunCommand("observe method");
        c1.observe();

        RunCommand c2 = new RunCommand("toObservable method");
        // 只返回一个可观察的对象,并不会马上执行
        // 只有当Observable真正被订阅之后,才会执行
        Observable ob = c2.toObservable();

        // 执行订阅,则会开始执行
        ob.subscribe(new Observer<String>() {

            // 命令执行完成之后
            public void onCompleted() {
                System.out.println("命令执行完成之后...");
            }

            // 命令有错误
            public void onError(Throwable e) {

            }

            // 命令执行返回
            public void onNext(String t) {
                System.out.println("执行返回:" + t);
            }

        });

        Thread.sleep(1000);
    }

    static class RunCommand extends HystrixCommand<String> {

        String msg;

        public RunCommand(String message) {
            super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));
            this.msg = message;
        }

        @Override
        protected String run() throws Exception {
            System.out.println(msg);
            return "success";
        }

    }
}

3、Hystrix配置

package com.atm.cloud.config;

import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandProperties;

public class MyTimeOutConfig extends HystrixCommand<String> {

    public MyTimeOutConfig() {
        // 第二种方法:
        // super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));

        // 超时时间设置成2s
        super(Setter.withGroupKey(
                HystrixCommandGroupKey.Factory.asKey("ExampleGroup"))
                .andCommandPropertiesDefaults(
                        HystrixCommandProperties.Setter()
                                .withExecutionTimeoutInMilliseconds(2000)));

        // 第一种方法:设置超时时间(设置成2s)
        HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(
                20000);
    }

    @Override
    protected String run() throws Exception {
        // 手动延迟3s
        // Thread.sleep(3000);
        System.out.println("执行命令...");
        return "Success";
    }

    // 回退方法
    @Override
    protected String getFallback() {
        System.out.println("执行回退...");
        // return super.getFallback();
        return "Fallback...";
    }

}
MyTimeOutConfig c = new MyTimeOutConfig();
String result = c.execute();
System.out.println(result);

3.1、全局超时配置

package com.atm.cloud;

import com.netflix.config.ConfigurationManager;
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;

/**
 * 设置全局超时时间
 *
 */
public class PropertyMain {
    public static void main(String[] args) {
        ConfigurationManager
                .getConfigInstance()
                .setProperty(
                        "hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds",
                        2000);
        PropertyCommand c = new PropertyCommand();
        String result = c.execute();
        System.out.println(result);
    }

    static class PropertyCommand extends HystrixCommand<String> {
        public PropertyCommand() {
            super(Setter.withGroupKey(HystrixCommandGroupKey.Factory
                    .asKey("ExampleGroup")));
        }

        @Override
        protected String run() throws Exception {
            Thread.sleep(3500);
            return "success";
        }

        @Override
        protected String getFallback() {
            return "fallback";
        }

    }
}

3.2、配置key

  • 有三个主要名称可为命令/命令组进行命名
    1. 命令组名称
    2. 命令名称
    3. 线程池名称
package com.atm.cloud;

import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandKey;
import com.netflix.hystrix.HystrixThreadPoolKey;

public class KeyCommand extends HystrixCommand<String> {

    public KeyCommand() {
        // 设置组名,每一个命令,Hystrix底层都会分配一个线程池去执行命令,它会使用一个map来维护这些线程池
        // 如果不提供线程池名称,则默认是使用组名作为线程池的key:Map<String,Pool>
        super(Setter
                .withGroupKey(HystrixCommandGroupKey.Factory.asKey("GroupKey"))
                .andCommandKey(HystrixCommandKey.Factory.asKey("CommandKey"))
                .andThreadPoolKey(
                        HystrixThreadPoolKey.Factory.asKey("ThreadPoolKey")));
    }

    @Override
    protected String run() throws Exception {
        return null;
    }

}

3.3、回退方法

  • 执行超时等失败情况(前面小节一直在测试超时回退)
  • 断路器打开(断路器:想象成保险丝)
  • 线程池满载
package com.atm.cloud.config;

import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandProperties;

public class FallbackMain {

    public static void main(String[] args) {
        FallbackCommand c = new FallbackCommand();
        String result = c.execute();
        System.out.println(result);
    }

    static class FallbackCommand extends HystrixCommand<String> {

        public FallbackCommand() {
            // 设置组名、打开断路器(不推荐代码打开断路器,实际开发中是实现特定逻辑才打开断路器,如频繁请求同一个服务均失败才打开)
            super(Setter.withGroupKey(
                    HystrixCommandGroupKey.Factory.asKey("ExampleGroup"))
                    .andCommandPropertiesDefaults(
                            HystrixCommandProperties.Setter()
                                    .withCircuitBreakerForceOpen(true)));// 强制打开断路器
        }

        @Override
        protected String run() throws Exception {
            return "success";
        }

        @Override
        protected String getFallback() {
            return "fallback";
        }
    }
}
  • 线程池满载情况回退,暂不做测试,后面小节进行测试

3.4、回退模式

  • Hystrix的回退机制比较灵活,可以在A命令中执行B中回退,如果B也执行失败,同样会触发B命令的回退,这样就形成一种链式的命令执行
  • 假设一个转账命令包含调用A银行扣款、B银行加款两个命令,其中一个命令失败后,再执行转账命令回退
  • 要做到多命令只执行一次回退的效果,CommandA和CommandB,不能有回退方法,如果CommandA命令执行失败,并且该命令有回退方法,此时将不会执行MainCommand的回退方法
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

'嗯哼。

生生不息,“折腾”不止,Thx

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值