Search code examples
netflix-eurekaspring-cloud-netflix

Set a list of acceped zones in Eureka


Is their a way to ignore zone or define list of accepted zone in Eureka, for example if we have 3 zones ( office, shahbour, joe )

I want the services in zone shahbour to only use services defined in shahbour primary and office as secondary and ignore all other zones in this example joe.

I tried it as below and it is working to prefer same zone but if their is no service on same zone it do load balance on all the others zones

spring:
  profiles: shahbour
eureka:
  instance:
    metadataMap:
      zone: shahbour
  client:
    region: lebanon
    serviceUrl:
      defaultZone: http://office:8761/eureka/
    preferSameZoneEureka: true
    availabilityZones:
      lebanon: shahbour,office

I thought setting availabilityZones set this but it is not .

This is for development environment where i am trying to setup each developer to use his machine as a zone and if service does not exist use office server as backup but don't use other developers .


Solution

  • I did not find any place to set the accepted list of zones in eureka but what i found is that we can create our custom ServerListFilter in Ribbon that is used in both Feign and Zuul so below is the code

    public class DevServerListFilter extends ZonePreferenceServerListFilter {
    
        private final List<String> acceptedZone = new ArrayList<>();
    
        public DevServerListFilter(String[] acceptedZones) {
            for (String zone: acceptedZones) {
                this.acceptedZone.add(zone);
            }
        }
    
        @Override
        public void initWithNiwsConfig(IClientConfig niwsClientConfig) {
            super.initWithNiwsConfig(niwsClientConfig);
        }
    
        @Override
        public List<Server> getFilteredListOfServers(List<Server> servers) {
            List<Server> zoneAffinityFiltered = super.getFilteredListOfServers(servers);
            Set<Server> candidates = Sets.newHashSet(zoneAffinityFiltered);
            Iterator serverIterator = candidates.iterator();
            while (serverIterator.hasNext()) {
                Server server = (Server)serverIterator.next();
                if(!acceptedZone.contains(server.getZone())) {
                    zoneAffinityFiltered.remove(server);
                }
    
            }
            return zoneAffinityFiltered;
        }
    
    
    } 
    

    The above filter extends ZonePreferenceServerListFilter with a check on list of accepted zones , any server not in this list is ignored .

    @Configuration
    @RibbonClients(defaultConfiguration = MyDefaultRibbonConfiguration.class)
    public class MyRibbonConfiguration {
    }
    

    Default configuration for all my clients

    @Configuration
    public class MyDefaultRibbonConfiguration {
    
    //    @Bean
    //    public IPing ribbonPing(IClientConfig config) {
    //        return new PingUrl();
    //    }
    
        @Bean
        public ServerListFilter<Server> ribbonServerListFilter(IClientConfig config,EurekaClientConfigBean eurekaClientConfigBean) {
            String[] availabilityZones = eurekaClientConfigBean.getAvailabilityZones(eurekaClientConfigBean.getRegion());
    
            DevServerListFilter filter = new DevServerListFilter(availabilityZones);
            filter.initWithNiwsConfig(config);
            return filter;
        }
    
    }
    

    The Configuration Code , note that this has to be in an excluded path from @ComponentScan as request in documents , and i used the availability zone property but any list can be used.

    github sample