Spring Cloud

Spring Cloud Hystrix 分析(二)之Hystr

2021-02-11  本文已影响0人  Blog

分析(一)中我们总结了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断路器配置!

上一篇下一篇

猜你喜欢

热点阅读