Spring cloud 如何配置zone Spring Cloud Zookeeper

Spring cloud 如何配置zone Spring Cloud Zookeeper,spring-cloud,apache-zookeeper,spring-cloud-config,apache-curator,spring-cloud-zookeeper,Spring Cloud,Apache Zookeeper,Spring Cloud Config,Apache Curator,Spring Cloud Zookeeper,我有3个前端应用程序和3个后端应用程序,假设1个虚拟机同时托管前端和后端应用程序,如下图所示,每个前端应用程序使用zookeeper支持的discovery client连接到后端 现在我想创建网络关联或区域,以便FE1连接到BE1(如果可用),如果BE1关闭,则连接到BE2/BE3。这能在春季云动物园实现吗 虽然这可以用尤里卡完成,但我更喜欢用zookeeper 编辑 好的,在eureka中,我们可以设置区域字段,ribbon可以根据从eureka检索到的每个服务器的区域字段在客户端中进行

我有3个前端应用程序和3个后端应用程序,假设1个虚拟机同时托管前端和后端应用程序,如下图所示,每个前端应用程序使用zookeeper支持的discovery client连接到后端

现在我想创建网络关联或区域,以便FE1连接到BE1(如果可用),如果BE1关闭,则连接到BE2/BE3。这能在春季云动物园实现吗

虽然这可以用尤里卡完成,但我更喜欢用zookeeper


编辑

好的,在eureka中,我们可以设置区域字段,ribbon可以根据从eureka检索到的每个服务器的区域字段在客户端中进行区域关联。zookeeper中存在问题,尽管ribbon使用了相同的zonepreference过滤器,但由于zookeeper不传递区域信息,因此始终保持未知,因此不应用区域过滤

我尝试的解决方法是在注册服务时将区域信息作为元数据传递,如下所示

spring:
  application:
    name: kp-zk-server
  cloud:
    zookeeper:
      discovery:
        metadata:
          zone: default
@Configuration
public class DefaultRibbonConfig {

    @Value("${archaius.deployment.zone:default}")
    private String zone;

    private Predicate<Server> filter = server -> {
        if (server instanceof ZookeeperServer) {
            ZookeeperServer zkServer = (ZookeeperServer) server;
            String str = zkServer.getInstance().getPayload().getMetadata().get("zone");
            return zone.equals(str);
        }
        return true;
    };

    @Bean
    public ServerListFilter<Server> ribbonServerListFilter(IClientConfig config) {
        return new ServerListFilter<Server>() {

            @Override
            public List<Server> getFilteredListOfServers(List<Server> servers) {
                List<Server> selected = servers.stream().filter(filter).collect(Collectors.toList());
                return selected.isEmpty() ? servers : selected;
            }
        };
    }

} 
现在,在客户端创建功能区配置中,从元数据中检索区域信息作为筛选器,如下所示

spring:
  application:
    name: kp-zk-server
  cloud:
    zookeeper:
      discovery:
        metadata:
          zone: default
@Configuration
public class DefaultRibbonConfig {

    @Value("${archaius.deployment.zone:default}")
    private String zone;

    private Predicate<Server> filter = server -> {
        if (server instanceof ZookeeperServer) {
            ZookeeperServer zkServer = (ZookeeperServer) server;
            String str = zkServer.getInstance().getPayload().getMetadata().get("zone");
            return zone.equals(str);
        }
        return true;
    };

    @Bean
    public ServerListFilter<Server> ribbonServerListFilter(IClientConfig config) {
        return new ServerListFilter<Server>() {

            @Override
            public List<Server> getFilteredListOfServers(List<Server> servers) {
                List<Server> selected = servers.stream().filter(filter).collect(Collectors.toList());
                return selected.isEmpty() ? servers : selected;
            }
        };
    }

} 
问题

现在的问题是没有启用/使用我的自定义筛选器类,如果我使用
@RibbonClients

@RibbonClients(defaultConfiguration = DefaultRibbonConfig.class)

但是,如果我使用
ribbon.NIWSServerListFilterClassName
声明,则不会应用筛选器,但在这种情况下,我无法设置zone属性,需要对zone属性进行硬编码

据我所知,这是不可能的,因为Zookeeper是现成的。 但是,您可以通过使用
spring cloud loadbalancer
和自定义
ServiceInstanceSupplier
来实现相同的结果,该自定义
ServiceInstanceSupplier扩展了
DiscoveryClientServiceInstanceSupplier
,并根据已设置的给定元数据过滤实例,或者,如果没有符合条件的实例,则返回发现的实例的完整列表,以便为您提供一些回退。 这是一个通用的解决方案,可以解决您的问题,即使您在同一个数据中心运行


希望这有帮助

据我所知,这是不可能的,因为Zookeeper是现成的。 但是,您可以通过使用
spring cloud loadbalancer
和自定义
ServiceInstanceSupplier
来实现相同的结果,该自定义
ServiceInstanceSupplier扩展了
DiscoveryClientServiceInstanceSupplier
,并根据已设置的给定元数据过滤实例,或者,如果没有符合条件的实例,则返回发现的实例的完整列表,以便为您提供一些回退。 这是一个通用的解决方案,可以解决您的问题,即使您在同一个数据中心运行


希望这有帮助

就我所能做到的而言,区域工作都是在ribbon中完成的,而不是在eureka中。@Spencergib是的,我同意,但ribbon从eureka获取区域信息,但是在zookeeper的情况下,区域信息始终是未知的,因为zookeeper中没有区域字段。更新了问题,现在问题是我的serverfilter没有被考虑DzooKeeper支持元数据。如果我们只是缺少元数据的拉区,我们当然可以这样做。@Spencergib是的,那会更好,我应该为此创建JIRA吗?然而,我的另一个问题是为什么我不能添加自定义过滤器?在功能区中,是否只有一个过滤器?源代码在这里很抱歉,您必须问一个单独的问题。就我所能做的而言,区域工作都是在ribbon中完成的,而不是在eureka中。@Spencergib是的,我同意,但是ribbon从eureka获取区域信息,但是在zookeeper的情况下,区域信息始终是未知的,因为zookeeper中没有区域字段。更新了问题,现在问题是我的serverfilter没有被考虑DzooKeeper支持元数据。如果我们只是缺少元数据的拉区,我们当然可以这样做。@Spencergib是的,那会更好,我应该为此创建JIRA吗?然而,我的另一个问题是为什么我不能添加自定义过滤器?在功能区中,是否只有一个过滤器?源代码在这里抱歉,您必须另外问一个问题。