当前位置: 首页 > 知识库问答 >
问题:

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

朱祺
2023-03-14

因此,我们有一个用作父级的启动器,它具有各种模板和自动配置,可以加载模拟客户端。

假客户端在下面使用eureka发现来迭代服务。

下面是我们的一个外国客户的例子:

导入组织。springframework。云对外开放。假装客户;

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

在使用此spring boot(以及cloud starter)作为父级(在pom.xml中)的项目中,我希望能够转到属性文件并执行如下操作:

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

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

那么,有没有办法通过丝带属性或其他方式来实现呢?

最好不修改起始代码?

问题是:我们如何通过使用属性文件更改外部客户端返回的实例。从本质上讲,我们如何超越starter和eureka auto 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;
    }
}

我注意到上面的代码导致我的项目慢了很多。此外,由于使用反射和方面,它非常古怪。

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

当然,这可能意味着我们必须在每个模板中包括调试支持、模拟客户端和每个微服务的自动配置。

思想?

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

决定代理。带子listOfServers=

共有1个答案

魏澄邈
2023-03-14

以下配置在bootstrap.yml适合我,

ribbon:
  eureka:
    enabled: false

my-service:
  ribbon:
    listOfServers: 192.168.1.217:9010

我在zuul代理中配置它,以便它可以引用未在同一eureka中注册的服务。这样,它将禁用所有eureka查找。

---更新了---

参考下面的链接,它可以指定一些服务使用指定的服务器列表,而不禁用所有的eureka查找。如何禁用eureka查找特定@FAIgnClient,指定

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

为你效劳

 类似资料:
  • 我希望在运行时传递变量,一旦war文件部署在tomcat上。如何使用classplath中的application.properties以及另一个属性文件ex。abcd.properties位于specific directory.am基本上希望设置额外的类路径,并从该路径中的属性文件中读取值,以及war部署的默认类路径位置。 我使用Spring boot。其中一种方法是将所有属性传递到数据库端,

  • 当目录树中的任何内容发生更改时,cro run会停止服务器、重新编译并重新启动服务器。那太好了。 但是,在开发客户端UI和使用NPX/纱线/网页包时,还需要另外一个步骤来生成

  • 我构建了一个访问数据库并从中提取数据的Spring-Boot应用程序。一切正常,但我想从外部. Properties文件配置表名。 比如: 我想找点东西,但没找到。 您可以使用注释访问外部属性。 所以我的问题是:有没有办法配置表名?或者我可以更改/拦截hibernate发送的查询吗? 解决方案: 好的,hibernate 5适用于。所以我创建了自己的。 此外,这篇关于NamingStrategy的

  • 本文向大家介绍Java下http下载文件客户端和上传文件客户端实例代码,包括了Java下http下载文件客户端和上传文件客户端实例代码的使用技巧和注意事项,需要的朋友参考一下 一、下载客户端代码 上述代码只适合下载小文件,如果下载大文件则会出现  Exception in thread "main" java.lang.OutOfMemoryError: Java heap space 错误,所以

  • 我有一个Web服务,我试图使用以下客户端代码调用它: 在服务器端(Tomcat),webservice实现如下: CxfAdd。java: CxfAddImpl。java: 但是,当我运行客户端代码时,在服务器端我得到以下错误: 似乎我没有发送ws-addressing属性,有人能帮我找出代码中的错误或缺失吗?非常感谢。

  • 简单验证器 向属性添加“验证”例程的快速方法是使用 validates() 装饰者。属性验证器可以引发异常,停止改变属性值的过程,或者将给定值更改为其他值。与所有属性扩展一样,验证程序只由普通的userland代码调用;当ORM填充对象时不会发出验证程序:: from sqlalchemy.orm import validates class EmailAddress(Base): __