美文网首页Spring Cloud
Spring Cloud Hystrix 分析(二)之Hystr

Spring Cloud Hystrix 分析(二)之Hystr

作者: Blog | 来源:发表于2021-02-11 21:41 被阅读0次

    分析(一)中我们总结了Hystrix的流程图,从流程图中我们可以大致了解到Hystrix的工作原理,本节则开始进行流程图的细化分析和总结,加深我们对Hystrix的理解!


    HystrixAutoConfiguration

    @Configuration
    @ConditionalOnClass({ Hystrix.class, HealthIndicator.class })
    @AutoConfigureAfter({ HealthIndicatorAutoConfiguration.class })
    public class HystrixAutoConfiguration {
    
        @Bean
        @ConditionalOnEnabledHealthIndicator("hystrix")
        public HystrixHealthIndicator hystrixHealthIndicator() {
            return new HystrixHealthIndicator();
        }
    }
    

    当前笔者对应的spring-cloud-netflix-core版本比较低(1.3.0.RC1),所以只有Hystrix的健康检查类,HystrixHealthIndicator主要是Hystrix健康指标相关的实现,上报断路器状态


    ConditionalOnEnabledHealthIndicator

    @Retention(RetentionPolicy.RUNTIME)
    @Target({ ElementType.TYPE, ElementType.METHOD })
    @Documented
    @Conditional(OnEnabledHealthIndicatorCondition.class)
    public @interface ConditionalOnEnabledHealthIndicator {
        /**
         * 健康指标名称
         */
        String value();
    }
    

    OnEnabledHealthIndicatorCondition

    class OnEnabledHealthIndicatorCondition extends OnEnabledEndpointElementCondition {
        OnEnabledHealthIndicatorCondition() {
            super("management.health.", ConditionalOnEnabledHealthIndicator.class);
        }
    }
    

    OnEnabledEndpointElementCondition

    /**
    * 自定义条件
    */
    abstract class OnEnabledEndpointElementCondition extends SpringBootCondition {
        private final String prefix;
        private final Class<? extends Annotation> annotationType;
    
        OnEnabledEndpointElementCondition(String prefix,
                Class<? extends Annotation> annotationType) {
            this.prefix = prefix;
            this.annotationType = annotationType;
        }
    
        @Override
        public ConditionOutcome getMatchOutcome(ConditionContext context,
                AnnotatedTypeMetadata metadata) {
            AnnotationAttributes annotationAttributes = AnnotationAttributes
                    .fromMap(metadata.getAnnotationAttributes(this.annotationType.getName()));
            //健康指标名称:hystrix
            String endpointName = annotationAttributes.getString("value");
            //根据健康指标名称获取是否配置了management.health.hystrix.enabled属性
            ConditionOutcome outcome = getEndpointOutcome(context, endpointName);
            if (outcome != null) {
                return outcome;
            }
            //默认处理方式,获取是否配置了management.health. defaults.enabled属性,缺省默认值为true
            return getDefaultEndpointsOutcome(context);
        }
    
        protected ConditionOutcome getEndpointOutcome(ConditionContext context,
                String endpointName) {
            RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
                    context.getEnvironment(), this.prefix + endpointName + ".");
            if (resolver.containsProperty("enabled")) {
                boolean match = resolver.getProperty("enabled", Boolean.class, true);
                return new ConditionOutcome(match,
                        ConditionMessage.forCondition(this.annotationType).because(
                                this.prefix + endpointName + ".enabled is " + match));
            }
            return null;
        }
    
        protected ConditionOutcome getDefaultEndpointsOutcome(ConditionContext context) {
            RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
                    context.getEnvironment(), this.prefix + "defaults.");
            boolean match = Boolean.valueOf(resolver.getProperty("enabled", "true"));
            return new ConditionOutcome(match,
                    ConditionMessage.forCondition(this.annotationType).because(
                            this.prefix + "defaults.enabled is considered " + match));
        }
    }
    

    通过@ConditionalOnEnabledHealthIndicator("hystrix")这个自定义条件注解,设置management.health.hystrix.enabled或者设置management.health.defaults.enabled属性,判断HystrixHealthIndicator实例是否进行实例化,下面我们就来分析下HystrixHealthIndicator具体的职责


    HystrixHealthIndicator健康检查指标

    public class HystrixHealthIndicator extends AbstractHealthIndicator {
    
        private static final Status CIRCUIT_OPEN = new Status("CIRCUIT_OPEN");
    
        @Override
        protected void doHealthCheck(Builder builder) throws Exception {
            List<String> openCircuitBreakers = new ArrayList<String>();
    
            //从HystrixCommandMetrics收集所有断路器
            for (HystrixCommandMetrics metrics : HystrixCommandMetrics.getInstances()) {
                HystrixCircuitBreaker circuitBreaker = HystrixCircuitBreaker.Factory
                        .getInstance(metrics.getCommandKey());
                if (circuitBreaker != null && circuitBreaker.isOpen()) {
                    openCircuitBreakers.add(metrics.getCommandGroup().name() + "::"
                            + metrics.getCommandKey().name());
                }
            }
    
            //如果断路器集合大于1,那么说明存在断路情况,更新hystrix健康状态
            if (openCircuitBreakers.size() > 0) {
                builder.status(CIRCUIT_OPEN).withDetail("openCircuitBreakers",
                        openCircuitBreakers);
            }
            else {
                //默认是开路状态
                builder.up();
            }
        }
    
    }
    

    如果服务都是处于正常情况,那么我们通过访问当前应用的/health获取健康状态会得到如下信息

    {
     "hystrix": {
             "status": "UP"
         }
    }
    

    如果当前应用有服务处于断路状态/熔断,那么我们访问当前应用的/health获取健康状态会得到如下信息

    {
    "hystrix": {
            "openCircuitBreakers": [
                "Service::Function"
            ],
            "status": "CIRCUIT_OPEN"
        }
    }
    

    总结:HystrixHealthIndicator主要负责获取HystrixCommandMetrics收集的断路器信息步骤7(断路器健康状况)并更新Hystrix的健康指标状态等信息,外部通过访问/health获取指标信息,便于得知当前应用内部的健康状况。下一节我们将分析HystrixCircuitBreakerConfiguration断路器配置!

    相关文章

      网友评论

        本文标题:Spring Cloud Hystrix 分析(二)之Hystr

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