如何配置区域Spring Cloud Zookeeper

时间:2019-02-26 12:40:02

标签: spring-cloud apache-zookeeper spring-cloud-config apache-curator spring-cloud-zookeeper

我有一个3个前端应用程序和3个后端应用程序,假设1个虚拟机同时托管前端和后端应用程序,如下图所示,每个前端应用程序使用发现连接到后端由Zookeeper驱动的客户端。

enter image description here

现在,我想创建网络亲缘关系或区域,以使FE1连接到BE1(如果可用),如果BE1断开则连接到BE2 / BE3。可以在spring-cloud-zookeeper中实现吗?

尽管可以使用eureka来完成,但是我更喜欢使用zookeeper。


编辑

好吧,在eureka中,我们可以设置区域字段,并且功能区可以基于从eureka中为每个服务器检索的区域字段在客户端中进行区域亲缘关系。问题是在Zookeeper中,尽管功能区使用相同的zonepreference过滤器,但是由于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 :(得分:0)

据我所知,开箱即用Zookeeper是不可能的。 但是,您可以通过使用import { FILTER_CARDS, FETCH_CARDS } from '../X/Y'; const initialState = { myPayload: [], filteredPayload: [] }; export default function (state = initialState, action) { const { type, myPayload = [], value } = action; const handler = { [FETCH_CARDS]: { ...state, myPayload, }, [FILTER_CARDS]: { ...state, filteredPayload: state.myPayload.filter(({ name }) => name.toLowerCase().match(value)), }, }; return handler[type] || state; } 和自定义[FILTER_CARDS]: { ...state, filteredPayload: (state.myPayload.type == ('student' || 'teacher') ? (state.myPayload.filter(({ name }) => name.toLowerCase().match(value)), state.myPayload.filter(({ age }) => age.toLowerCase().match(value)), state.myPayload.filter(({ height }) => height.toLowerCase().match(value))) : (state.myPayload.filter(({ name }) => name.toLowerCase().match(value)), state.myPayload.filter(({ country }) => country.toLowerCase().match(value)), state.assetsPayload.filter(({ state }) => state.toLowerCase().match(value)))), }, 来实现相同的结果,该自定义扩展spring-cloud-loadbalancer并根据已设置的给定元数据过滤实例,或者返回发现的完整列表实例(如果没有一个符合标准)为您提供一些备用。 这是一个通用解决方案,即使您正在同一数据中心中运行,也可以解决您的问题。

希望这会有所帮助!