简体   繁体   English

如何配置区域Spring Cloud Zookeeper

[英]How to configure zone Spring Cloud Zookeeper

I've a 3 front-end application and 3 back end application, Let us say 1 Virtual Machine hosts both front-end and back end application as shown in below diagram, Each front-end application connects to back end using discovery client powered by zookeeper. 我有一个3个前端应用程序和3个后端应用程序,让我们说1个虚拟机同时托管前端和后端应用程序,如下图所示,每个前端应用程序都使用由以下驱动程序提供的发现客户端连接到后端动物园管理员。

在此处输入图片说明

Now I want to create network affinity or zone such that FE1 connects to BE1 if available, if BE1 is down connect to BE2/BE3. 现在,我想创建网络亲缘关系或区域,以使FE1连接到BE1(如果可用),如果BE1断开则连接到BE2 / BE3。 Can this be achieved in spring-cloud-zookeeper? 可以在spring-cloud-zookeeper中实现吗?

Though this can be done using eureka, but I would prefer to do it using zookeeper. 虽然可以使用尤里卡(eureka)完成此操作,但是我更喜欢使用zookeeper。


EDIT 编辑

Ok in eureka we can set the zone field and ribbon can do zone affinity in client based on zone field retrieved from eureka for each server. 好的,在eureka中,我们可以设置区域字段,并且功能区可以根据从eureka检索到的每个服务器的区域字段来在客户端中进行区域亲缘关系。 The issue is in zookeeper though ribbon uses the same zonepreference filter but it since zookeeper does not pass the zone info, it always remains UNKNOWN , hence zone filtering is not applied. 问题是在Zookeeper中,尽管功能区使用相同的zonepreference过滤器,但是由于Zookeeper未通过区域信息,因此它始终保持UNKNOWN ,因此未应用区域过滤。

As workaround what I tried is pass zone info as metadata while registering service as shown below. 作为解决方法,我尝试的是在注册服务时将区域信息作为元数据传递,如下所示。

spring:
  application:
    name: kp-zk-server
  cloud:
    zookeeper:
      discovery:
        metadata:
          zone: default

Now in client create ribbon configuration as retrieve the zone info from metadata as filter as shown below. 现在在客户端中创建功能区配置,如下所示从元数据中检索区域信息作为过滤器。

@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;
            }
        };
    }

} 

boostrap.yml boostrap.yml

archaius:
  deployment:
    zone: Zone1
spring:
  application:
    name: kp-zk-consumer
  cloud:
    zookeeper:
      dependency:
        enabled: true
        resttemplate:
          enabled: false
      discovery:
        enabled: true
      default-health-endpoint: /actuator/health
      dependencies:
        kWebClient:
          path: /kp-zk-server
          loadBalancerType: ROUND_ROBIN
          required: true
#ribbon:
#  NIWSServerListFilterClassName: io.github.kprasad99.zk.KZoneAffinityServerFilter

Problem 问题

Now the problem is my custom filter class is not being enabled/used, ribbon is still using the default zone filter, if I define the configuration using @RibbonClients 现在的问题是我的自定义过滤器类未启用/使用,如果我使用@RibbonClients定义配置,功能区仍在使用默认区域过滤器

@RibbonClients(defaultConfiguration = DefaultRibbonConfig.class)

However, if I declare using ribbon.NIWSServerListFilterClassName the filter is not applied, but in this case I cannot set the zone property, need to hardcode the zone property. 但是,如果我声明使用ribbon.NIWSServerListFilterClassName ,则不会应用该过滤器,但是在这种情况下,我无法设置区域属性,需要对区域属性进行硬编码。

As far as I know this isn't possible with Zookeeper out of the box. 据我所知,开箱即用Zookeeper是不可能的。 However, you could achieve the same result by using spring-cloud-loadbalancer and a custom ServiceInstanceSupplier which extends DiscoveryClientServiceInstanceSupplier and filters the instances based on given metadata that has been set, or return the complete list of discovered instances if none matched the criteria to provide you some fallback. 但是,您可以使用spring-cloud-loadbalancer和自定义ServiceInstanceSupplier来实现相同的结果,该ServiceInstanceSupplier扩展了DiscoveryClientServiceInstanceSupplier并根据已设置的给定元数据过滤实例,或者如果发现的实例不符合提供的条件,则返回发现的实例的完整列表你一些后备。 This is a generic solution that could solve your question even if you're running in the same datacenter for example. 这是一个通用解决方案,即使您在同一数据中心中运行,也可以解决您的问题。

Hope this helps! 希望这可以帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM