Hystrix从原理到详细使用

版权声明:本文为CSDN博主「Lin~Xu」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/rekingman/article/details/96132094

目录

一、什么是Hystrix

二、Hystrix的原理

1、命令模式

2、观察者模式

3、原理分析

三、如何使用Hystrix

四、详细配置与Hystrix监控优化

1、详细配置

 2、监控优化​

 五、总结

一、什么是Hystrix

  • 源自Martin Fowler的Circuit Breaker,即断路器。“断路器”本身是一种开关装置,用于线路上的过载保护,当线路发生短路时,会及时切断故障电路,防止一系列问题。
  • 在分布式架构中,断路器模式也是类似,当某个单元发生故障,及时切断联系,防止线程因调用故障服务而长时间等待而不被释放,最终导致故障在分布式系统中的蔓延。
  • Hystrix实现的功能有:服务降级、服务熔断、线程和信号隔离、请求缓存、请求合并、以及服务监控等功能。(对于请求缓存功能,个人建议不要使用,除非该实例是单机运行,否则会出现数据不一致的问题)

二、Hystrix的原理

在讲解Hystrix的原理之前,先介绍两种设计模式,分别是:命令模式、观察者模式。

1、命令模式

在这里插入图片描述

以上就是命令模式的图示:Invoker为行为请求者、Receiver为行为实现者。以下列出这种模式的伪代码:

public class InvokerAndReceiver {
    /**
     * 命令的抽象
     */
    interface Command {
        void execute();
    }

    /**
     * 调用者
     */
    static class Invoker {
        private Command command;

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

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

    /**
     * 业务的具体实现
     */
    static class Receiver {
        public void action() {
            //do some task.
            System.out.println("doing...");
        }
    }

    /**
     * 命令的封装
     */
    static class CommandImpl implements Command {
        private Receiver receiver;
        public CommandImpl(Receiver receiver) {
            this.receiver = receiver;
        }
        @Override
        public void execute() {
            receiver.action();
        }
    }

    public static void main(String[] args) {
        Receiver receiver=new Receiver();
        Command command=new CommandImpl(receiver);
        Invoker invoker=new Invoker();
        invoker.setCommand(command);
        invoker.execute();
    }
}

2、观察者模式

观察者模式的实现模型与订阅模式类似,这里以Hystrix底层使用的RxJava作为介绍。

public static void main(String[] args) {
   //被观察者,也是事件源
        Observable<String> source=Observable.create(subscriber -> {
            subscriber.onNext("Hello !");
            subscriber.onNext("welcome to subscribe it.");
          //事件源通知异常。
          	subscriber.onError(new NullPointerException("error"));
          //结束
          	subscriber.onCompleted();
        });
   //观察者
        Subscriber<String> subscriber=new Subscriber<String>() {
            @Override
            public void onCompleted() {
              //完成后的工作
            }

            @Override
            public void onError(Throwable throwable) {
              //观察者在这处理异常的事务
            }

            @Override
            public void onNext(String s) {
              //获取事件源的持续信息,如果事件源持续发布事件。
                System.err.println(s);
            }
        };
        source.subs
}

以下是观察者模式的两种分类:

  • 热观察
    • 每个观察者都可以在事件源的中途加入,这会造成看到的是加入后的局部信息。
  • 冷观察
    • 事件源需要等待观察者加入后,才发布事件,这样,看到的是全部过程。

好了,介绍完这两种模式,我们才能够分析Hystrix的底层原理。

3、原理分析

​ 首先,我们从@HystrixCommand注解入手。

@HystrixCommand(fallbackMethod = "fallBack")
    public String hiService() {
        return restTemplate.getForObject("http://provider/zone?",String.class);
    }

@HystrixCommand注解会为当前方法创建一个HystrixCommand对象,这个类的主要作用是命令模式中对于Command的封装,执行命令有如下两个方法:

//用于异步请求,返回的是Future对象,包含服务执行结束时会返回的结果对象。 
public Future<R> queue() {
        /*
         * The Future returned by Observable.toBlocking().toFuture() does not implement the
         * interruption of the execution thread when the "mayInterrupt" flag of Future.cancel(boolean) is set to true;
         * thus, to comply with the contract of Future, we must wrap around it.
         */
        final Future<R> delegate = toObservable().toBlocking().toFuture();
    
        final Future<R> f = new Future<R>() {
            @Override
            public boolean cancel(boolean mayInterruptIfRunning) {
                if (delegate.isCancelled()) {
                    return false;
                }
                if (HystrixCommand.this.getProperties().executionIsolationThreadInterruptOnFutureCancel().get()) {
                    interruptOnFutureCancel.compareAndSet(false, mayInterruptIfRunning);
        		}

                final boolean res = delegate.cancel(interruptOnFutureCancel.get());

                if (!isExecutionComplete() && interruptOnFutureCancel.get()) {
                    final Thread t = executionThread.get();
                    if (t != null && !t.equals(Thread.currentThread())) {
                        t.interrupt();
                    }
                }

                return res;
			}
            @Override
            public boolean isCancelled() {
                return delegate.isCancelled();
			}
            @Override
            public boolean isDone() {
                return delegate.isDone();
			}
            @Override
            public R get() throws InterruptedException, ExecutionException {
                return delegate.get();
            }
            @Override
            public R get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
                return delegate.get(timeout, unit);
            }
        	
        };

        /* special handling of error states that throw immediately */
        if (f.isDone()) {
            try {
                f.get();
                return f;
            } catch (Exception e) {
                Throwable t = decomposeException(e);
                if (t instanceof HystrixBadRequestException) {
                    return f;
                } else if (t instanceof HystrixRuntimeException) {
                    HystrixRuntimeException hre = (HystrixRuntimeException) t;
                    switch (hre.getFailureType()) {
					case COMMAND_EXCEPTION:
					case TIMEOUT:
						// we don't throw these types from queue() only from queue().get() as they are execution errors
						return f;
					default:
						// these are errors we throw from queue() as they as rejection type errors
						throw hre;
					}
                } else {
                    throw Exceptions.sneakyThrow(t);
                }
            }
        }

        return f;
    }
//用于同步执行,从依赖服务返回单一对象结果;调用的是queue.get
    public R execute() {
        try {
            return queue().get();
        } catch (Exception e) {
            throw Exceptions.sneakyThrow(decomposeException(e));
        }
    }

除去HystrixCommand,还有HystrixObservableCommand,该类主要实现两个方法:

observe() 这是一个热观察
toObservable() 这是一个冷观察
实际上,excute() 的实现是queue(),而queue中,我们可以看到有如下:

//使用了冷观察;并且转化成为Future异步对象。
final Future<R> delegate = toObservable().toBlocking().toFuture();

因此,我们可以知道,Hstrix命令的运行有如下两个重要部分:

事件源处理(冷、热观察模式)
同、异步处理(同步等待返回结果,异步利用Future对象,可以异步处理其它工作,并且最后获取future中需要的结果返回即可)
以下说一下Hystrix的命令执行,用图说明:

在Hystrix中,断路器概念核心,以下是它的定义:

public interface HystrixCircuitBreaker {

    //每个Hystrix命令请求,在执行之前,都会调用这个方法,判断当前是否可以执行。
    public boolean allowRequest();
	//判断开闭状态
    public boolean isOpen();
	//当断路器处于半开状态,且命令运行成功,则用于关闭断路器
    void markSuccess();
}

 断路器的实现有多个,采用内部类实现:

//都不实现
static class NoOpCircuitBreaker implements HystrixCircuitBreaker {
        @Override
        public boolean allowRequest() {
            return true;
        }
        @Override
        public boolean isOpen() {
            return false;
        }
        @Override
        public void markSuccess() {
        }
    }
  //默认实现
  static class HystrixCircuitBreakerImpl implements HystrixCircuitBreaker {
        private final HystrixCommandProperties properties;
        private final HystrixCommandMetrics metrics;
        /* track whether this circuit is open/closed at any given point in time (default to false==closed) */
        private AtomicBoolean circuitOpen = new AtomicBoolean(false);
        /* when the circuit was marked open or was last allowed to try a 'singleTest' */
        private AtomicLong circuitOpenedOrLastTestedTime = new AtomicLong();
    //还有具体几个方法的实现。
  }

对于断路器来说,断路器会根据本身的状态,即断路器是否开启,来决定这个HystrixCommand命令是否执行,还是调用fallBack进行降级,断路器开启和关闭的度量标准如下,由度量对象metrics获取healthCount进行判断,这个时间窗口默认为10S:

QPS在预设的阈值之内,则返回false,默认为20。
如果错误请求百分比,在预设阈值之下,则返回false。
源码如下:

@Override
        public boolean isOpen() {
            if (circuitOpen.get()) {
                return true;
            }
            HealthCounts health = metrics.getHealthCounts();
            // check if we are past the statisticalWindowVolumeThreshold
            if (health.getTotalRequests() < properties.circuitBreakerRequestVolumeThreshold().get()) {
                // we are not past the minimum volume threshold for the statisticalWindow so we'll return false immediately and not calculate anything
                return false;
            }
            if (health.getErrorPercentage() < properties.circuitBreakerErrorThresholdPercentage().get()) {
                return false;
            } else {
                // our failure rate is too high, trip the circuit
                if (circuitOpen.compareAndSet(false, true)) {
                    // if the previousValue was false then we want to set the currentTime
                    circuitOpenedOrLastTestedTime.set(System.currentTimeMillis());
                    return true;
                } else {
                    return true;
                }
            }
        }

判断是否允许:

@Override
        public boolean allowRequest() {
          //这个地方要注意,我们看到了,强制开启的优先级大于强制关闭。
            if (properties.circuitBreakerForceOpen().get()) {
                return false;
            }
            if (properties.circuitBreakerForceClosed().get()) {
                isOpen();
                return true;
            }
          	//这里通过两个方法的结合使用,实现关闭、开启的切换
            return !isOpen() || allowSingleTest();
        }
//这个方法的功能是尝试允许命令请求;
 public boolean allowSingleTest() {
            long timeCircuitOpenedOrWasLastTested = circuitOpenedOrLastTestedTime.get();
            // 1) if the circuit is open
            // 2) and it's been longer than 'sleepWindow' since we opened the circuit
            if (circuitOpen.get() && System.currentTimeMillis() > timeCircuitOpenedOrWasLastTested + properties.circuitBreakerSleepWindowInMilliseconds().get()) {
                // We push the 'circuitOpenedTime' ahead by 'sleepWindow' since we have allowed one request to try.
                // If it succeeds the circuit will be closed, otherwise another singleTest will be allowed at the end of the 'sleepWindow'.
                if (circuitOpenedOrLastTestedTime.compareAndSet(timeCircuitOpenedOrWasLastTested, System.currentTimeMillis())) {
                  //尝试允许请求,则使得断路器处于半开状态。
                    return true;
                }
            }
            return false;
        }

以上是允许请求的实现:

通过allowSingleTest,尝试允许请求访问。
通过设置休眠时间,在休眠时间过去之后,则将断路器处于“半开状态”,这种半开状态,实际是就是允许命令请求的执行,如果执行又失败,或者超时,则又将断路器置于全开状态;并且在休眠时间之后,尝试允许,继续处于半开状态。
关闭断路器的实现如下:

public void markSuccess() {
            if (circuitOpen.get()) {
              //关闭断路器
                if (circuitOpen.compareAndSet(true, false)) {
                    //win the thread race to reset metrics
                    //Unsubscribe from the current stream to reset the health counts stream.  This only affects the health counts view,
                    //and all other metric consumers are unaffected by the reset
                  //重置统计信息
                    metrics.resetStream();
                }
            }
        }

以上就是Hystrix的原理部分,但是,我们忽略了一个重要部分,即Hystrix的线程隔离。

 a.舱壁模式

 如果读者对Docker已经熟悉,那么,舱壁模式也一定不会陌生。Docker就是通过舱壁模式,实现进程之间的隔离,使得容器与容器之间不会互相影响。

​ 而Hystrix则是使用该模式,对线程进行隔离,使得不同的Hystrix命令请求可以由不同的线程池(可以指定)创建线程去向服务提供者发送请求。

  • 优点
    • 应用自身得到保护,线程池被填满,应用其它部分正常工作。
    • 线程池隔离,使得不同的服务依赖之间不会互相影响,能够保证服务的稳定。
  • 缺点
    • 使用线程池隔离,会使得请求发送会有一小部分的延时(几ms)。

综合以上优缺点,如果你的服务是一个要求实时性非常高,哪怕是几ms也不行,那么建议不要使用线程池隔离;而如果可以容忍几ms的延时,那么,使用线程池带来的稳定性是没法媲美的。 

三、如何使用Hystrix

Hystrix的使用有两种方式:一种是使用优雅的注解形式,一种是使用灵活的代码继承。在这里,我只讲解注解形式的使用。

  • 依赖
<dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
  • 启动主类

第一种方式

@SpringBootApplication
@EnableCircuitBreaker

第二种方式

@SpringCloudApplication

@SpringCloudApplication这个注解的具体内容如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public @interface SpringCloudApplication {
}
  • 在服务方法上添加 @HystrixCommand注解
  • /**
         * 同步执行
         *
         * @return 返回一个直接结果
         */
        @HystrixCommand(fallbackMethod = "fallbackMethod",ignoreExceptions = IOException.class,commandKey = "methodname",groupKey = "组键,一般按类名来",threadPoolKey = "线程池的key")
        public String synRequest() {
            return restTemplate.getForObject("URL", String.class);
        }

    注意:threadPoolKey 属性如果没有指定,那么,则会根据groupKey来分配线程池。

  • 处理不同的命令执行的错误结果
    /**
         * private、public、protected all can define this method.
         * but you should  care of one tip, this method should be in thisClass.
         */
        private String defaultFallBack(Throwable throwable) {
            if (throwable instanceof IOException) {
                //do io service fallback
            } else if (throwable instanceof HttpClientErrorException) {
                //do request error fallback
            } else {
                return "";
            }
            return "";
        }

注意:通过添加Throwable throwable方法参数,并且对类型进行判断,则可以做不同的服务降级的处理。

  • 异步请求

 

/**
     * 异步
     * can use ignoreException specify the type of ex to avoid service fallback by throwing anyEx
     * expect HystrixBadRequestException.So,use this character,we can catch the different type of ex do different solve.
     * just to add the <code>Throwable e</code> as the fallback Method parameter.
     *
     * @return 返回异步对象。
     */
    @HystrixCommand(fallbackMethod = "defaultFallBack",commandProperties = {
            //设置具体实例的超时时间,如果不设置,则采用全局的默认1S
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "5000"),
            //下面的超时配置默认为启动,可以修改为false。来保证某个实例不启用超时
            @HystrixProperty(name = "execution.timeout.enabled",value = "false")
    })
    public Future<String> asyncRequest() {
        return new AsyncResult<String>() {
            //这里是异步请求
            @Override
            public String invoke() {
                return restTemplate.getForObject("URL", String.class);
            }
        };
    }
  • 请求合并
@HystrixCollapser(batchMethod = "batchRequest",collapserProperties = {
            //等待时间
            @HystrixProperty(name = "timeDelayInMillseconds",value = "100"),
            //每个批处理最大的请求数
            @HystrixProperty(name = "maxRequestsInBatch",value = "10"),
  			//不要开启请求缓存。这个功能就是个毫无意义的功能。
            @HystrixProperty(name = "requestCacheEnabled",value = "false")
    })
    public String singleRequest(){
        return null;
    }
    public List<String> batchRequest(){
        return restTemplate.getForObject("URL",List.class);
    }

注意:请求合并,需要服务端有多一个提供批量响应的接口。当每个用户请求过来,按照以上配置,每隔100ms就会将批量请求发送出去。或者满足达到最大批量处理数,则发送出去。这种情况很适合在网络繁忙或者线程资源紧张的时候,因为合并之后,只会发送一次网络请求。

合并前的请求图示:

[外链图片转存失败(img-ymv1aWtF-1563257116166)(C:\Users\SAMSUNG\Desktop\暑假\笔记\微服务架构\Snipaste_2019-07-15_21-56-06.jpg)]

合并请求后的图示:

[外链图片转存失败(img-abLJkFUo-1563257116169)(C:\Users\SAMSUNG\Desktop\暑假\笔记\微服务架构\Snipaste_2019-07-15_21-56-15.jpg)]

关于Hystrix的使用就讲解到这里,后面会讲解详细配置与优化、监控

四、详细配置与Hystrix监控优化

1、详细配置

  • Command属性

    execution配置 ,控制的是HystrixCommand.run()的执行。

#隔离策略;默认为THREAD
可通过@HystrixProperty (name="execution.isolation.strategy", value= "THREAD")注解设置 
#value有两种,一种是线程THREAD;一种是信号量 SEMAPHORE。

       execution.isolation. 七hread.timeoutinMilliseconds

#run方法执行超时策略;默认1000MS
@HystrixProperty(name= "execution.isolation.thread.timeoutinMilliseconds",value="2000") 注解来设置 

      execution.timeout.enabled: 该属性用来配置HystrixCommand.run()的 执行是否启用超时时间。 默认为true, 如果设置为false,那么超时设置不起作用。

可通过@HystrixProperty(name= "execution.timeout.enabled", value="false")注解来设置 

      execution.isolation.thread.interruptOnTimeout: 该属性用来配置当 HystrixCommand.run()执行超时的时候是否要将它中断。

可通过@HystrixProperty(name="execution.isolation.thread.interruptOnTimeout", value="false")注解来设置

      execution.isolation. thread.interruptOnCancel: 该属性用来配置当 HystrixCommand.run()执行被取消的时候是否要将它中断。

可通过@HystrixProperty(name="execution.isolation.thread.interruptOnCancel", value="false")注解来设置
  • fallback配置

      fallback.isolation.semaphore.maxConcurrentRequests: 该属性用来 设置从调用线程中允许HystrixCommand.getFallback()方法执行的最大并发请求数。 当达到最大并发请求数时,后续的请求将会被拒绝并抛出异常。

#默认为20
@HystrixProperty (name="fallback.isolation.semaphore.maxConcurrentRequests", value="20")注解来设置

      fallback.enabled: 该属性用来设置服务降级策略是否启用, 如果设置为false, 那么当请求失败或者拒绝发生时, 将不会调用HystrixCommand.getFallback() 来执行服务降级逻辑。

#默认为true
可通过@HystrixProperty(name= "fallback. enabled", value="false")注解来设置
  • circuitBreaker配置

      circuitBreaker.enabled: 该属性用来确定当服务请求命令失败时, 是否使用 断路器来跟踪其健康指标和熔断请求。

#默认为true
可通过H@ystrixProperty(name="circuitBreaker. enabled",value="false")注解来设置

      circuitBreaker.requestVolumeThreshold: 该属性用来设置在滚动时间窗 中,断路器熔断的最小请求数。 例如,默认该值为20的时候,如果滚动时间窗(默 认10秒)内仅收到了19个请求,即使这19个请求都失败了,断路器也不会打开。

#默认为20
可以@HystrixProperty(name= "circuitBreaker.requestVolumeThreshold", value="30")注解

      circuitBreaker.sleepWindowinMilliseconds: 该属性用来设置当断路器 打开之后的休眠时间窗。 休眠时间窗结束之后,会将断路器置为 “半开” 状态,尝试熔断的请求命令,如果依然失败就将断路器继续设置为 “打开” 状态,如果成功 就设置为 “关闭” 状态。

#默认5000MS
@HystrixProperty (name="circuitBreaker.sleepWindowinMilliseconds",value="3000") 注解来设置

      circuitBreaker.errorThresholdPercentage: 该属性用来设置断路器打开 的错误百分比条件。 例如,默认值为 50 的情况下,表示在滚动时间窗中,在请求 数量超过circuitBreaker.reques七VolumeThreshold阅值的前提下,如果 错误请求数的百分比超过50, 就把断路器设置为 “打开” 状态, 否则就设置为 “关 闭 ” 状态。

可通 过@HystrixProperty (name="circuitBreaker.errorThresholdPercentage", value="40") 注解来设置

      circuitBreaker.forceOpen: 如果将该属性设置为 true, 断路器将强制进入“打 开” 状态, 它会拒绝所有请求。 该属性优先于 circuitBreaker.forceClosed 属性。

@HystrixProperty (name="circuitBreaker. forceOpen", value="true")注解来设置

      circuitBreaker.forceClosed: 如果将该属性设置为 true, 断路器将强制进入 “关闭” 状态, 它会接收所有请求。 如果 circuitBreaker.forceOpen 属性为 true, 该属性不会生效。

 可通过@HystrixProperty(name= "circui七Breaker.forceClosed", value="true")注解来设置
  • metrics配置

metrics.rollingStats.timeinMilliseconds: 该属性用来设置滚动时间窗 的长度, 单位为毫秒。 该时间用于断路器判断健康度时需要收集信息的持续时间。 断路器在收集指标信息的时候会根据设置的时间窗长度拆分成多个 “ 桶” 来累计各 度量值, 每个 “ 桶” 记录了一段时间内的采集指标。 例如, 当采用默认值10000毫 秒时, 断路器默认将其拆分成10个桶(桶的数量也可通过metrics.rollingStats.numBuckets参数设置), 每个桶记录1000毫秒内的指标信息。

@HystrixProperty(name="metrics.rollingStats.timeinMilliseconds", value="20000")注解来设置

metrics.rollingstats.numBuckets: 该属性用来设置滚动时间窗统计指标 信息时划分 “ 桶” 的数量。

@HystrixProperty(name="metrics.rollingStats.numBuckets",value="20")注 解来设置

注意:metrics.rollingStats.timeinMilliseconds与metrics.rollingStats.numBuckets必须存在整除关系。

metrics.rollingPercente.enabled: 该属性用来设置对命令执行的延迟 是否使用百分位数来跟踪和计算。 如果设置为false, 那么所有的概要统计都将返回 -1。

@HystrixProperty (name="metrics.rollingPercentile.enabled", value="false")注解 来设置

metrics.rollingPercentile.timeinMilliseconds: 该属性用来设置百分 位统计的滚动窗口的持续时间, 单位为毫秒。

默认值60000
@HystrixProperty(name="metrics.rollingPercentile.timeinMilli seconds", value="6OOOO")注解来设置

metrics.rollingPercentile.numBuckets: 该属性用来设置百分位统计滚 动窗口中使用 “桶 ”的数量。
默认值6

@HystrixProperty (name="metrics.rollingPercentile.numBuckets",value="6")注解来设 置

注意:以上两者同样保持整除关系。

metrics.rollingPercentile.bucketSize: 该属性用来设置在执行过程中 每个 “桶 ” 中保留的最大执行次数。 如果在滚动时间窗内发生超过该设定值的执行 次数, 就从最初的位置开始重写。 例如, 将该值设置为100, 滚动窗口为10秒, 若 在10秒内一个 “桶” 中发生了500次执行, 那么该 “桶” 中只保留 最后的100次执 行的统计。 另外, 增加该值的大小将会增加内存量的消耗, 并增加排序百分位数所 需的计算时间。

#de 100
@HystrixProperty(name="metrics. rollingPercentile.bucketSize",value= "120")注解来设置

metrics.healthSnapshot.intervalinMilliseconds: 该属性用来设置采 集影响断路器状态的健康快照(请求的成功、 错误百分比)的间隔等待时间。

#默认500
通过@HystrixProperty(name="metrics.healthSnapshot.intervalinMilliseconds",value= "600")注解来设置
  • collapser属性

@HystrixCollapser中的collapserProperties属性来设置.
maxRequestsinBatch: 该参数用来设置 一次请求合并批处理中允许的最大请求数。 默认为最大整数
timerDelayinMilliseconds: 该参数用来设置批处理过程中每个命令延迟的时 间,单位为毫秒。 默认为10MS

  • thread Pool属性

配置方式

threadPoolProperties = {
              @HystrixProperty(name = "coreSize",value = "20")
              //线程池的最大队列长度。
              ,@HystrixProperty(name = "maxQueueSize",value = "-1"),
              //队列最大拒绝阈值,没有达到队列最大值,也能拒绝。
              @HystrixProperty(name = "queueSizeRejectionThreshold",value = "5")
      }

 2、监控优化​

以上我们学习了Hystrix的详细配置,知道了这么多项的配置信息,每一项都与我们服务的性能、稳定性息息相关,但是,这么多的配置信息又令人有点乱,不知道如何入手,不知道自己的系统的配置到底应该是怎么的。

​ 没关系,与Hystrix相对应的一款开源监控工具,Hystrix-DashBoard,也称为仪表盘,就是用于实时监控服务的性能、请求等信息。下面我将介绍怎么使用这款监控工具。

  • 引入依赖
<!-- metrics 监控-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
  • 启动类注解
@EnableHystrixDashboard//开启仪表盘
  • 配置文件
management:
  endpoints:
    web:
      exposure:
        include: ["hystrix.stream"]
  • SpringBoot2.0注册路径Bean
//在启动类中注册     
@Bean
    public ServletRegistrationBean servletRegistrationBean() {
        ServletRegistrationBean registration = new ServletRegistrationBean(
                new HystrixMetricsStreamServlet(), "/hystrix.stream");
        registration.setName("hystrixServlet");
        registration.setLoadOnStartup(1);
        return registration;
    }

启动浏览器访问IP:PORT/hystrix即可。有如下页面:


于是,我们可以根据服务的监控状况,对配置进行修改、优化,达到最符合我们应用需求的配置。

 五、总结

Hystrix提供服务降级、线程隔离、服务熔断等功能
Hystrix至少涉及了:命令模式、观察者模式、舱壁模式
Hystrix配置项很多,但是,我们可以根据具体要求进行优化。利用DashBoard的监控。
Hystrix的特别要点:
同区域Zone的服务,降级后,可以访问其它服务。但是对于熔断的服务就采用降级策略。
对于不同Zone的服务,降级后,不可以访问其它Zone下的相同服务。
因此:使用时候,应注意,部分业务不跨区,使用Hystrix;部分业务跨区,不适用Hystrix。


————————————————
版权声明:本文为CSDN博主「Lin~Xu」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/rekingman/article/details/96132094

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值