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 .
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.