Как настроить зону Spring Cloud Zookeeper - PullRequest
0 голосов
/ 26 февраля 2019

У меня есть 3 интерфейсных приложения и 3 серверных приложения. Допустим, 1 виртуальная машина содержит как интерфейсное, так и серверное приложение, как показано на диаграмме ниже. Каждое интерфейсное приложение подключается к серверной части с помощью функции обнаруженияклиент работает на zookeeper.

enter image description here

Теперь я хочу создать сетевую привязку или зону, такую, чтобы FE1 подключался к BE1, если он доступен, если BE1 не работает, подключайтесь кВЕ2 / BE3.Может ли это быть достигнуто в spring-cloud-zookeeper?

Хотя это можно сделать с помощью eureka, но я бы предпочел сделать это с помощью zookeeper.


EDIT

Хорошо, в eureka мы можем установить поле зоны, и лента может выполнять привязку зоны в клиенте на основе поля зоны, полученного из eureka для каждого сервера.Проблема в zookeeper, хотя лента использует тот же фильтр настройки зоны, но он не передает информацию о зоне zookeeper, но всегда остается UNKNOWN, следовательно, фильтрация зоны не применяется.

В качестве обходного путипопытался передать информацию о зоне в качестве метаданных при регистрации службы, как показано ниже.

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

} 

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

Проблема

Теперь проблема в том, что мой пользовательский класс фильтра не включен / не используется, лента все еще использует фильтр зоны по умолчанию,если я определяю конфигурацию с помощью @RibbonClients

@RibbonClients(defaultConfiguration = DefaultRibbonConfig.class)

Однако, если я объявляю с использованием ribbon.NIWSServerListFilterClassName, фильтр не применяется, но в этом случае я не могу установить свойство зоны, необходимо жестко закодировать свойство зоны,

1 Ответ

0 голосов
/ 26 февраля 2019

Насколько я знаю, это невозможно с Zookeeper из коробки.Тем не менее, вы могли бы достичь того же результата, используя spring-cloud-loadbalancer и пользовательский ServiceInstanceSupplier, который расширяет DiscoveryClientServiceInstanceSupplier и фильтрует экземпляры на основе заданных заданных метаданных, или возвращает полный список обнаруженных экземпляров, если ни один не соответствует критериямчтобы предоставить вам запасной вариант.Это общее решение, которое может решить ваш вопрос, даже если вы, например, работаете в одном центре обработки данных.

Надеюсь, это поможет!

...