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断路器配置!