代码之家  ›  专栏  ›  技术社区  ›  Menelaos

使用属性文件更改外部客户机返回的实例(over ride starter和eureka auto ribbon行为)

  •  0
  • Menelaos  · 技术社区  · 6 年前

    介绍

    因此,我们有一个初学者,我们正在使用作为父,这有各种模板和自动配置,加载外国客户机以及。

    导入org.springframework.cloud云.openfeign.FeignClient文件;

    @FeignClient(name="decide-proxy")
    public interface DecideControllerApiClient extends DecideControllerApi {
    }
    

    eureka.client.filter.enabled=true
    eureka.client.filter.services.doc-tools.host=localhost
    eureka.client.filter.services.doc-tools.port=8015
    

    我现在有办法做到这一点,但它涉及到使用方面和反射,这似乎减慢了我的项目-这是一个巨大的丑陋的黑客。

    那么,有没有一种方法可以通过ribbon属性或其他方式来实现呢?

    不修改起始代码?

    如何通过使用属性文件来更改外部客户机返回的实例。 从本质上说,我们如何才能超越起动机和尤里卡汽车功能区的行为。

    当前黑客攻击

    所以我看到了以下链接: https://stackoverflow.com/a/42413801/1688441

    基于这一点,我创造了以下似乎有效的方法:

       import com.netflix.appinfo.InstanceInfo;
        import eureka.InstanceBuildVersionProperties.InstanceHostFilter;
        import lombok.RequiredArgsConstructor;
        import org.aspectj.lang.ProceedingJoinPoint;
        import org.aspectj.lang.annotation.Around;
        import org.aspectj.lang.annotation.Aspect;
        import org.slf4j.Logger;
        import org.slf4j.LoggerFactory;
        import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
        import org.springframework.cloud.client.ServiceInstance;
        import org.springframework.cloud.netflix.eureka.EurekaDiscoveryClient.EurekaServiceInstance;
        import org.springframework.stereotype.Component;
    
        import java.lang.reflect.Field;
        import java.net.URI;
        import java.util.ArrayList;
        import java.util.Arrays;
        import java.util.List;
        import java.util.Map;
        import java.util.stream.Collectors;
    
        @RequiredArgsConstructor
        @Aspect
        public class EurekaInstanceHostFilter {
            private final Logger logger = LoggerFactory.getLogger(this.getClass());
    
            private final String versionMetadataKey;
            private final InstanceBuildVersionProperties filters;
    
            @SuppressWarnings("unchecked")
            @Around("execution(public * org.springframework.cloud.netflix.eureka.EurekaDiscoveryClient.getInstances(..))")
            public Object filterInstances(ProceedingJoinPoint jp) throws Throwable {
                if (filters == null || !filters.isEnabled()) logger.error("Should not be filtering...");
                List<ServiceInstance> instances = (List<ServiceInstance>) jp.proceed();
    
                String serviceId = (String) jp.getArgs()[0];
                InstanceHostFilter filter = filters.getServices().get(serviceId);
    
                if(filter != null){
                    instances.forEach( instance -> {
    
    
                        try {
    
                            Class<?> clazz = EurekaServiceInstance.class;
                            Class<?> clazzInfo = InstanceInfo.class;
    
                            Field instanceField = clazz.getDeclaredField("instance");
                            instanceField.setAccessible(true);
                            InstanceInfo instanceInfo = (InstanceInfo) instanceField.get(instance);
    
                            String originalHostName =instanceInfo.getHostName();
                            int originalPort =instanceInfo.getPort();
    
                            //SET THE VALUES
    
                            String changeInstanceId = filter.getHost() + ":" + instance.getServiceId() + ":" +filter.getPort();
                            setField(instanceInfo, clazzInfo, "instanceId", changeInstanceId );
    
                            //HomePageURL
                            String newHomePageUrl = instanceInfo.getHomePageUrl().replace(originalHostName, filter.getHost())   .replace(originalPort+"", filter.getPort()+"");
                            setField(instanceInfo, clazzInfo, "homePageUrl", newHomePageUrl );
    
                            //StatusPageUrl
                            String statusPageUrl = instanceInfo.getStatusPageUrl().replace(originalHostName, filter.getHost())  .replace(originalPort+"", filter.getPort()+"");
                            setField(instanceInfo, clazzInfo, "statusPageUrl", statusPageUrl );
    
                            //healthCheckURL
                            String healthCheckUrl = instanceInfo.getHealthCheckUrl().replace(originalHostName, filter.getHost())    .replace(originalPort+"", filter.getPort()+"");
                            setField(instanceInfo, clazzInfo, "healthCheckUrl", healthCheckUrl );
    
                            //hostName
                            String hostName = instanceInfo.getHostName().replace(originalHostName, filter.getHost());
                            setField(instanceInfo, clazzInfo, "hostName", hostName );
    
                            setIntField(instanceInfo, clazzInfo, "port", filter.getPort());
    
                        } catch (NoSuchFieldException e) {
                            e.printStackTrace();
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
    
    
                    });
    
                }
    
                return instances;
            }
    
            private void setField(Object instanceInfo, Class<?> clazzInfo, String fieldName, String value) throws NoSuchFieldException, IllegalAccessException {
                Field instanceId = clazzInfo.getDeclaredField(fieldName);
                instanceId.setAccessible(true);
                instanceId.set(instanceInfo, value);
            }
    
            private void setIntField(Object instanceInfo, Class<?> clazzInfo, String fieldName, int value) throws NoSuchFieldException, IllegalAccessException {
                Field instanceId = clazzInfo.getDeclaredField(fieldName);
                instanceId.setAccessible(true);
                instanceId.setInt(instanceInfo, value);
            }
    
        }
    
        import org.springframework.beans.factory.annotation.Value;
        import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
        import org.springframework.boot.context.properties.EnableConfigurationProperties;
        import org.springframework.context.annotation.Bean;
        import org.springframework.context.annotation.Configuration;
    
        @Configuration
        @ConditionalOnProperty(name = "eureka.client.filter.enabled", havingValue = "true")
        @EnableConfigurationProperties(InstanceBuildVersionProperties.class)
        public class EurekaInstanceHostFilterAutoConfig {
    
            @Value("${eureka.instance.metadata.keys.version:instanceBuildVersion}")
            private String versionMetadataKey;
    
            @Bean
            @ConditionalOnProperty(name = "eureka.client.filter.enabled", havingValue = "true")
            public EurekaInstanceHostFilter eurekaInstanceBuildVersionFilter(InstanceBuildVersionProperties filters) {
                return new EurekaInstanceHostFilter(versionMetadataKey, filters);
            }
        }
    
    
    import lombok.Getter;
    import lombok.Setter;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import java.util.HashMap;
    import java.util.Map;
    
    import static org.apache.commons.lang3.ArrayUtils.contains;
    
    @ConfigurationProperties("eureka.client.filter")
    public class InstanceBuildVersionProperties {
        private final Logger logger = LoggerFactory.getLogger(this.getClass());
    
        /**
         * Indicates whether or not service instances versions should be filtered
         */
        @Getter @Setter
        private boolean enabled = false;
    
        /**
         * Map of service instance version filters.
         * The key is the service name and the value configures a filter set for services instances
         */
        @Getter
        private Map<String, InstanceHostFilter> services = new HashMap<>();
    
        public boolean isKept(String serviceId) {
            logger.debug("Considering service {} instance", serviceId);
            if (services.containsKey(serviceId)) {
                InstanceHostFilter filter = services.get(serviceId);
                //TODO:
                return true;
            }
            return true;
        }
    
        @Getter @Setter
        public static class InstanceHostFilter {
            /**
             * host to use
             */
            private String host;
            private int port;
        }
    }
    

    此外,由于使用了反射和方面,因此非常粗糙。

    其他想法

    唯一的另一个想法是在启动器本身中开始有条件地加载配置。因此,我可以根据应用程序属性文件中的属性,尝试加载一个外部客户机或另一个外部客户机。

    思想?

    更新

    我们尝试使用属性文件和一个功能区属性加上假名,但这不起作用。比如:

    decide-proxy.ribbon.listOfServers=

    1 回复  |  直到 6 年前
        1
  •  2
  •   Simon    6 年前

    中的以下配置引导.yml为我工作,

    ribbon:
      eureka:
        enabled: false
    
    my-service:
      ribbon:
        listOfServers: 192.168.1.217:9010
    

    ---更新---

    参考下面的链接,它可以指定一些服务来使用指定的服务器列表而不禁用所有eureka查找。 How to disable eureka lookup on specific @FeignClient

     my-service:
        ribbon:     
          NIWSServerListClassName:com.netflix.loadbalancer.ConfigurationBasedServerList
          listOfServers: server1:18201,server2:18201
    

    为您服务