Spring Cloud 发现多个服务版本

2024-01-10

我在问自己一个问题,但没有找到答案。也许这里有人对此有想法;-) 在 Spring Cloud 中使用服务注册表(Eureka)与 RestTemplate 和 Feign 客户端,我有不同的构建版本的同一服务。通过 Actuator 的 /info 端点记录构建版本。

{
"build": {
"version": "0.0.1-SNAPSHOT",
"artifact": "service-a",
"name": "service-a",
"group": "com.mycompany",
"time": 1487253409000
}
}
...
{
"build": {
"version": "0.0.2-SNAPSHOT",
"artifact": "service-a",
"name": "service-a",
"group": "com.mycompany",
"time": 1487325340000
}
}

有什么办法可以在客户致电时询问特定的构建版本吗? 我应该使用网关的路由过滤器来管理它吗?但我想版本检测仍然是一个问题......

好吧,任何建议表示赞赏。


好的。这是将构建版本注入到要由 Eureka 注册的服务(“service-a”)实例元数据中的代码:

@Configuration
@ConditionalOnClass({ EurekaInstanceConfigBean.class, EurekaClient.class })
public class EurekaClientInstanceBuildVersionAutoConfiguration {

    @Autowired(required = false)
    private EurekaInstanceConfig instanceConfig;

    @Autowired(required = false)
    private BuildProperties buildProperties;

    @Value("${eureka.instance.metadata.keys.version:instanceBuildVersion}")
    private String versionMetadataKey;

    @PostConstruct
    public void init() {
        if (this.instanceConfig == null || buildProperties == null) {
            return;
        }
        this.instanceConfig.getMetadataMap().put(versionMetadataKey, buildProperties.getVersion());
    }
}

这是验证“service-b”内元数据传输的代码:

@Component
public class DiscoveryClientRunner implements CommandLineRunner {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private DiscoveryClient client;

    @Override
    public void run(String... args) throws Exception {
        client.getInstances("service-a").forEach((ServiceInstance s) -> {
            logger.debug(String.format("%s: %s", s.getServiceId(), s.getUri()));
            for (Entry<String, String> md : s.getMetadata().entrySet()) {
                logger.debug(String.format("%s: %s", md.getKey(), md.getValue()));
            }
        });
    }
}

请注意,如果“虚线组成”(即“实例构建版本”),则元数据键强制采用驼峰式大小写。

这是我发现的根据版本过滤服务实例的解决方案:

@Configuration
@EnableConfigurationProperties(InstanceBuildVersionProperties.class)
public class EurekaInstanceBuildVersionFilterAutoConfig {

    @Value("${eureka.instance.metadata.keys.version:instanceBuildVersion}")
    private String versionMetadataKey;

    @Bean
    @ConditionalOnProperty(name = "eureka.client.filter.enabled", havingValue = "true")
    public EurekaInstanceBuildVersionFilter eurekaInstanceBuildVersionFilter(InstanceBuildVersionProperties filters) {
        return new EurekaInstanceBuildVersionFilter(versionMetadataKey, filters);
    }
}

@Aspect
@RequiredArgsConstructor
public class EurekaInstanceBuildVersionFilter {
    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();
        return instances.stream()
                .filter(i -> filters.isKept((String) jp.getArgs()[0], i.getMetadata().get(versionMetadataKey))) //DEBUG MD key is Camel Cased!
                .collect(Collectors.toList());
    }
}

@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, InstanceBuildVersionFilter> services = new HashMap<>();

    public boolean isKept(String serviceId, String instanceVersion) {
        logger.debug("Considering service {} instance version {}", serviceId, instanceVersion);
        if (services.containsKey(serviceId) && StringUtils.hasText(instanceVersion)) {
            InstanceBuildVersionFilter filter = services.get(serviceId);
            String[] filteredVersions = filter.getVersions().split("\\s*,\\s*");    // trimming
            logger.debug((filter.isExcludeVersions() ? "Excluding" : "Including") + " instances: " + Arrays.toString(filteredVersions));
            return contains(filteredVersions, instanceVersion) ? !filter.isExcludeVersions() : filter.isExcludeVersions();
        }
        return true;
    }

    @Getter @Setter
    public static class InstanceBuildVersionFilter {
        /**
         * Comma separated list of service version labels to filter
         */
        private String versions;
        /**
         * Indicates whether or not to keep the associated instance versions.
         * When false, versions are kept, otherwise they will be filtered out
         */
        private boolean excludeVersions = false;
    }
}

您可以为每个使用的服务指定预期或避免版本的列表,并且将相应地过滤发现。

logging.level.com.mycompany.demo=调试

eureka.client.filter.enabled=true

eureka.client.filter.services.service-a.versions=0.0.1-SNAPSHOT

如有任何建议,请作为评论提交。谢谢

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring Cloud 发现多个服务版本 的相关文章

随机推荐

  • AJAX 使用 CORS 获取自定义响应标头

    我的服务器随响应一起发送自定义标头 我得到了正确的响应数据 但我无法使用 jQuery 访问自定义标头getAllResponseHeaders 或 AngularJS http服务 我得到的只是content type 当我使用 DevT
  • pybot 和机器人命令行

    我尽了最大努力 但无法找到答案 无法找到 pybot 和机器人命令行之间的区别 这是实现相同任务 即执行机器人测试套件 案例 的两个不同选项吗 或者有一个特殊的规则说明何时使用pybot以及何时使用robot命令行运行机器人测试用例 请帮助
  • 如何使用 MSVC 在 C++ 中定义外部 C 结构返回函数?

    以下源文件将无法使用 MSVC 编译器 v15 00 30729 01 进行编译 stest c ifdef cplusplus extern C endif struct Test NB This may be extern when i
  • 如何以编程方式与 winlogon 交互?

    我有一个 Windows 服务 我想使用该服务通过帐户用户名和密码以编程方式解锁工作站 This article https technet microsoft com en us library dn751047 v ws 11 aspx
  • 检查字符串是否仅包含数字或仅包含字符 (R)

    我有这三个字符串 letters lt abc numbers lt 123 mix lt b1dd 如何检查这些字符串中哪一个仅包含字母或仅包含数字 在 R 中 letters仅应在仅字母检查中为 TRUE numbers仅在 NUMBE
  • Bash 中的行尾(新行)转义

    转义字符 可用于转义行尾 例如 echo This could be a very long line Output This could be a very long line 但是 行尾 新行 不是由 n其中有两个字符 转义的结果不应该
  • 为什么交换多维数组不是 noexcept ?

    我有以下片段 include
  • 根据关系表获取多个表的结果

    我有 dbo Users 表 Id Name 1 John 2 Mary 3 Michael 然后我有 dbo Phones 表 Id Phonenumber 10 1234 11 5555 然后我有 dbo Relationship 表
  • Laravel Eloquent 按关系表列排序

    我尝试对产品进行排序shop products表格依据pinned专栏来自shop products options table products Shop Product with options gt function query qu
  • lein REPL 服务器启动超时

    在基于 liberator 的 clojure 项目中 我们使用 datomic 作为数据库 将我们的本地开发数据库迁移到 S3 托管的数据库并在我们的 project clj 上添加所需的依赖项后 我们无法启动 REPL 但 Libera
  • django-filter:使用 ChoiceFilter 并根据请求进行选择

    我正在使用 django filter 并需要添加ChoiceFilter根据我收到的请求进行选择 我正在阅读 ChoiceFilter 的文档 但它说 This filter matches values in its choices a
  • 将 csv 最快导入数据库表

    我已经实现了一个导入功能 该功能从 Asp Net 应用程序中的 csv 文件获取数据 文件大小可以从几 kb 到最大 10 MB 不等 但是 当发生导入并且文件大小 gt 50000 时 大约需要 20 分钟 这时间太多了 我需要在 2
  • 如何在由javascript创建的html中显示动态url图像

    我试图通过 Javascript 生成的动态链接直接以 HTML 形式显示图像 function dynamicUrl var url http xxx xxx xxx dynamic variables jpg return url 我的
  • 适用于多类型用户的猫鼬模型

    我正在用 MEAN stack 为学生和老师建立一种社交网络 学生有自己的帐户页面 与教师的帐户页面不同 我有一个供教师和学生使用的注册页面 注册时 用户必须使用 select html 标签选择帐户的 类型 学生或教师 我想要一个代表两种
  • UITableView reloadData 导致 UITextField 辞职 FirstResponder

    我有一个文本字段 设置为使用输入的每个字母更改 tableView 的数据源 并调用 reloadData 但由于某种原因 每次输入字母时 键盘都会消失 有人知道为什么吗 您的文本字段正在辞职 因为重新加载的单元格被发送 resignFir
  • Three.js:在场景角落显示世界坐标轴

    我想在相机的右下角显示指示世界坐标方向 x y z 的箭头 就像在 Maya 中所做的那样 这样当围绕对象旋转相机或在场景中移动时 您仍然可以识别世界坐标的方向 我尝试使用两种不同的方法来完成此任务 但到目前为止都没有奏效 我有一个带有三个
  • [IllegalStateException]:Spark 结构化流正在终止流查询并出现错误

    我创建了一个 Spark 结构化流应用程序 在应用程序中 我从 Kafka 主题中提取数据 为了恢复目的 我使用检查点 我面临的挑战如下 ERROR StreamExecution Query id cf9e0f0a 653a 4246 a
  • MySQL 在一个查询中进行多个连接?

    我有以下查询 SELECT dashboard data headline dashboard data message dashboard messages image id FROM dashboard data INNER JOIN
  • SWIG ImportError:未定义的符号:_Py_RefTotal

    我对 SWIG 真的很陌生 我尝试编译 SWIG 中给出的示例 但出现以下错误 python Python 2 6 5 r265 79063 Apr 16 2010 13 09 56 GCC 4 4 3 on linux2 Type hel
  • Spring Cloud 发现多个服务版本

    我在问自己一个问题 但没有找到答案 也许这里有人对此有想法 在 Spring Cloud 中使用服务注册表 Eureka 与 RestTemplate 和 Feign 客户端 我有不同的构建版本的同一服务 通过 Actuator 的 inf