feign+hystrix根据serviceId配置hystrix.command

在使用feign+hystrix时,hystrix.command相关的属性的优先级是

hystrix.command.FeignClient#Method() -> hystrix.command.default

如果我们希望优先级是

hystrix.command.FeignClient#Method() -> hystrix.command.FeignClient#name -> hystrix.command.default

目前通过配置没有找到相关的方法,要想实现,就只有改代码了;但是改代码要改哪些呢?
1、覆盖原来的HystrixFeign$Builder
2、重写SetterFactory方法

代码如下

import com.netflix.hystrix.HystrixCommand;
import feign.Feign;
import feign.hystrix.HystrixFeign;
import feign.hystrix.SetterFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.core.env.ConfigurableEnvironment;

@Configuration
@ConditionalOnClass({ HystrixCommand.class, HystrixFeign.class })
public class FeignHystrixConfiguration {

    @Autowired
    private ConfigurableEnvironment environment;


    @Bean
    @Scope("prototype")
    @ConditionalOnProperty(name = "feign.hystrix.enabled", matchIfMissing = false)
    public Feign.Builder feignHystrixBuilder() {
        return HystrixFeign.builder().setterFactory(getSetterFactory());
    }

    private SetterFactory getSetterFactory(){
        return new FmSetterFactory(environment);
    }
}
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandKey;
import com.netflix.hystrix.HystrixCommandProperties;
import feign.Feign;
import feign.Target;
import feign.hystrix.SetterFactory;
import org.springframework.core.env.ConfigurableEnvironment;
import java.lang.reflect.Method;
import java.util.Optional;

public class FmSetterFactory implements SetterFactory {

    private static final String HYSTRIX_COMMAND_PREFIX = "hystrix.command";

    private ConfigurableEnvironment environment;

    public FmSetterFactory(ConfigurableEnvironment environment) {
        this.environment = environment;
    }

    @Override
    public HystrixCommand.Setter create(Target<?> target, Method method) {
        String groupKey = target.name();
        String commandKey = Feign.configKey(target.type(), method);


        return HystrixCommand.Setter
                .withGroupKey(HystrixCommandGroupKey.Factory.asKey(groupKey))
                .andCommandKey(HystrixCommandKey.Factory.asKey(commandKey))
                .andCommandPropertiesDefaults(
                        initHystrixCommandPropertiesSetter(target));
    }

    private HystrixCommandProperties.Setter initHystrixCommandPropertiesSetter(Target<?> target) {
        HystrixCommandProperties.Setter setter = HystrixCommandProperties.Setter();
        Boolean circuitBreakerEnabled = getHystrixCommandBooleanPropValue(target.name(), "circuitBreaker.enabled");
        Optional.ofNullable(circuitBreakerEnabled).ifPresent(v -> setter.withCircuitBreakerEnabled(v));
        Integer circuitBreakerRequestVolumeThreshold = getHystrixCommandIntegerPropValue(target.name(), "circuitBreaker.requestVolumeThreshold");
        Optional.ofNullable(circuitBreakerRequestVolumeThreshold).ifPresent(v -> setter.withCircuitBreakerRequestVolumeThreshold(v));
        Integer circuitBreakerSleepWindowInMilliseconds = getHystrixCommandIntegerPropValue(target.name(), "circuitBreaker.sleepWindowInMilliseconds");
        Optional.ofNullable(circuitBreakerSleepWindowInMilliseconds).ifPresent(v -> setter.withCircuitBreakerSleepWindowInMilliseconds(v));
        Integer circuitBreakerErrorThresholdPercentage = getHystrixCommandIntegerPropValue(target.name(), "circuitBreaker.errorThresholdPercentage");
        Optional.ofNullable(circuitBreakerErrorThresholdPercentage).ifPresent(v -> setter.withCircuitBreakerErrorThresholdPercentage(v));
        Boolean circuitBreakerForceOpen = getHystrixCommandBooleanPropValue(target.name(), "circuitBreaker.forceOpen");
        Optional.ofNullable(circuitBreakerForceOpen).ifPresent(v -> setter.withCircuitBreakerForceOpen(v));
        Boolean circuitBreakerForceClosed = getHystrixCommandBooleanPropValue(target.name(), "circuitBreaker.forceClosed");
        Optional.ofNullable(circuitBreakerForceClosed).ifPresent(v -> setter.withCircuitBreakerForceClosed(v));
        String executionIsolationStrategy = getHystrixCommandStringPropValue(target.name(), "execution.isolation.strategy");
        Optional.ofNullable(executionIsolationStrategy).ifPresent(v -> {
            try {
                setter.withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.valueOf(v));
            } catch (Exception e) {
            }
        });
        Integer executionTimeoutInMilliseconds = getHystrixCommandIntegerPropValue(target.name(), "execution.isolation.thread.timeoutInMilliseconds");
        Optional.ofNullable(executionTimeoutInMilliseconds).ifPresent(v -> setter.withExecutionTimeoutInMilliseconds(v));
        Boolean executionTimeoutEnabled = getHystrixCommandBooleanPropValue(target.name(), "execution.timeout.enabled");
        Optional.ofNullable(executionTimeoutEnabled).ifPresent(v -> setter.withExecutionTimeoutEnabled(v));

        Boolean executionIsolationThreadInterruptOnTimeout = getHystrixCommandBooleanPropValue(target.name(), "execution.isolation.thread.interruptOnTimeout");
        Optional.ofNullable(executionIsolationThreadInterruptOnTimeout).ifPresent(v -> setter.withExecutionIsolationThreadInterruptOnTimeout(v));
        Boolean executionIsolationThreadInterruptOnFutureCancel = getHystrixCommandBooleanPropValue(target.name(), "execution.isolation.thread.interruptOnFutureCancel");
        Optional.ofNullable(executionIsolationThreadInterruptOnFutureCancel).ifPresent(v -> setter.withExecutionIsolationThreadInterruptOnFutureCancel(v));
        Integer executionIsolationSemaphoreMaxConcurrentRequests = getHystrixCommandIntegerPropValue(target.name(), "execution.isolation.semaphore.maxConcurrentRequests");
        Optional.ofNullable(executionIsolationSemaphoreMaxConcurrentRequests).ifPresent(v -> setter.withExecutionIsolationSemaphoreMaxConcurrentRequests(v));
        Integer fallbackIsolationSemaphoreMaxConcurrentRequests = getHystrixCommandIntegerPropValue(target.name(), "fallback.isolation.semaphore.maxConcurrentRequests");
        Optional.ofNullable(fallbackIsolationSemaphoreMaxConcurrentRequests).ifPresent(v -> setter.withFallbackIsolationSemaphoreMaxConcurrentRequests(v));
        Boolean fallbackEnabled = getHystrixCommandBooleanPropValue(target.name(), "fallback.enabled");
        Optional.ofNullable(fallbackEnabled).ifPresent(v -> setter.withFallbackEnabled(v));
        Integer metricsRollingStatisticalWindowInMilliseconds = getHystrixCommandIntegerPropValue(target.name(), "metrics.rollingStats.timeInMilliseconds");
        Optional.ofNullable(metricsRollingStatisticalWindowInMilliseconds).ifPresent(v -> setter.withMetricsRollingStatisticalWindowInMilliseconds(v));
        Integer metricsRollingStatisticalWindowBuckets = getHystrixCommandIntegerPropValue(target.name(), "metrics.rollingStats.numBuckets");
        Optional.ofNullable(metricsRollingStatisticalWindowBuckets).ifPresent(v -> setter.withMetricsRollingStatisticalWindowBuckets(v));
        Boolean metricsRollingPercentileEnabled = getHystrixCommandBooleanPropValue(target.name(), "metrics.rollingPercentile.enabled");
        Optional.ofNullable(metricsRollingPercentileEnabled).ifPresent(v -> setter.withMetricsRollingPercentileEnabled(v));

        Integer metricsRollingPercentileWindowInMilliseconds = getHystrixCommandIntegerPropValue(target.name(), "metrics.rollingPercentile.timeInMilliseconds");
        Optional.ofNullable(metricsRollingPercentileWindowInMilliseconds).ifPresent(v -> setter.withMetricsRollingPercentileWindowInMilliseconds(v));
        Integer metricsRollingPercentileWindowBuckets = getHystrixCommandIntegerPropValue(target.name(), "metrics.rollingPercentile.numBuckets");
        Optional.ofNullable(metricsRollingPercentileWindowBuckets).ifPresent(v -> setter.withMetricsRollingPercentileWindowBuckets(v));

        Integer metricsRollingPercentileBucketSize = getHystrixCommandIntegerPropValue(target.name(), "metrics.rollingPercentile.bucketSize");
        Optional.ofNullable(metricsRollingPercentileBucketSize).ifPresent(v -> setter.withMetricsRollingPercentileBucketSize(v));

        Integer metricsHealthSnapshotIntervalInMilliseconds = getHystrixCommandIntegerPropValue(target.name(), "metrics.healthSnapshot.intervalInMilliseconds");
        Optional.ofNullable(metricsHealthSnapshotIntervalInMilliseconds).ifPresent(v -> setter.withMetricsHealthSnapshotIntervalInMilliseconds(v));

        Boolean requestCacheEnabled = getHystrixCommandBooleanPropValue(target.name(), "requestCache.enabled");
        Optional.ofNullable(requestCacheEnabled).ifPresent(v -> setter.withRequestCacheEnabled(v));

        Boolean requestLogEnabled = getHystrixCommandBooleanPropValue(target.name(), "requestLog.enabled");
        Optional.ofNullable(requestLogEnabled).ifPresent(v -> setter.withRequestLogEnabled(v));
        return setter;
    }


    private String getHystrixCommandStringPropValue(String key, String instanceProperty) {
        return getHystrixCommandStringPropValue(key, instanceProperty, null);
    }

    private Boolean getHystrixCommandBooleanPropValue(String key, String instanceProperty) {
        return getHystrixCommandBooleanPropValue(key, instanceProperty, null);
    }

    private Integer getHystrixCommandIntegerPropValue(String key, String instanceProperty) {
        return getHystrixCommandIntegerPropValue(key, instanceProperty, null);
    }

    private String getHystrixCommandStringPropValue(String key, String instanceProperty, String defaultValue) {
        return getHystrixCommandPropValue(key, instanceProperty, defaultValue, String.class);
    }

    private Boolean getHystrixCommandBooleanPropValue(String key, String instanceProperty, Boolean defaultValue) {
        return getHystrixCommandPropValue(key, instanceProperty, defaultValue, Boolean.class);
    }

    private Integer getHystrixCommandIntegerPropValue(String key, String instanceProperty, Integer defaultValue) {
        return getHystrixCommandPropValue(key, instanceProperty, defaultValue, Integer.class);
    }

    private <T> T getHystrixCommandPropValue(String key, String instanceProperty, T defaultValue, Class<T> type) {
        return getPropValue(HYSTRIX_COMMAND_PREFIX, key, instanceProperty, defaultValue, type);
    }


    private <T> T getPropValue(String propertyPrefix, String key, String instanceProperty, T defaultValue, Class<T> type) {
        String propName = new StringBuilder()
                .append(propertyPrefix)
                .append(".")
                .append(key)
                .append(".")
                .append(instanceProperty)
                .toString();
        T value =  environment.getProperty(propName, type);
        if(value==null){
            value = defaultValue;
        }
        return value;
    }
}

yaml 配配置

hystrix:
  command:
    "Client1#getTest3(String)": # FeignClient方法级
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 100
    client-1: # FeignClient级
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 1500
    default:  #所有使用Feign的service
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 2000
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值