package com.netflix.discovery.shared.resolver.aws;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.EurekaClientConfig;
import com.netflix.discovery.endpoint.EndpointUtils;
import com.netflix.discovery.shared.resolver.ClusterResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* A resolver that on-demand resolves from configuration what the endpoints should be.
*
* @author David Liu
*/
public class ConfigClusterResolver implements ClusterResolver<AwsEndpoint> {
private static final Logger logger = LoggerFactory.getLogger(ConfigClusterResolver.class);
private final EurekaClientConfig clientConfig;
private final InstanceInfo myInstanceInfo;
public ConfigClusterResolver(EurekaClientConfig clientConfig, InstanceInfo myInstanceInfo) {
this.clientConfig = clientConfig;
this.myInstanceInfo = myInstanceInfo;
}
@Override
public String getRegion() {
return clientConfig.getRegion();
}
@Override
public List<AwsEndpoint> getClusterEndpoints() {
if (clientConfig.shouldUseDnsForFetchingServiceUrls()) {
if (logger.isInfoEnabled()) {
logger.info("Resolving eureka endpoints via DNS: {}", getDNSName());
}
return getClusterEndpointsFromDns();
} else {
logger.info("Resolving eureka endpoints via configuration");
return getClusterEndpointsFromConfig();
}
}
private List<AwsEndpoint> getClusterEndpointsFromDns() {
String discoveryDnsName = getDNSName();
int port = Integer.parseInt(clientConfig.getEurekaServerPort());
// cheap enough so just re-use
DnsTxtRecordClusterResolver dnsResolver = new DnsTxtRecordClusterResolver(
getRegion(),
discoveryDnsName,
true,
port,
false,
clientConfig.getEurekaServerURLContext()
);
List<AwsEndpoint> endpoints = dnsResolver.getClusterEndpoints();
if (endpoints.isEmpty()) {
logger.error("Cannot resolve to any endpoints for the given dnsName: {}", discoveryDnsName);
}
return endpoints;
}
private List<AwsEndpoint> getClusterEndpointsFromConfig() {
String[] availZones = clientConfig.getAvailabilityZones(clientConfig.getRegion());
String myZone = InstanceInfo.getZone(availZones, myInstanceInfo);
Map<String, List<String>> serviceUrls = EndpointUtils
.getServiceUrlsMapFromConfig(clientConfig, myZone, clientConfig.shouldPreferSameZoneEureka());
List<AwsEndpoint> endpoints = new ArrayList<>();
for (String zone : serviceUrls.keySet()) {
for (String url : serviceUrls.get(zone)) {
try {
endpoints.add(new AwsEndpoint(url, getRegion(), zone));
} catch (Exception ignore) {
logger.warn("Invalid eureka server URI: {}; removing from the server pool", url);
}
}
}
if (logger.isDebugEnabled()) {
logger.debug("Config resolved to {}", endpoints);
}
if (endpoints.isEmpty()) {
logger.error("Cannot resolve to any endpoints from provided configuration: {}", serviceUrls);
}
return endpoints;
}
private String getDNSName() {
return "txt." + getRegion() + '.' + clientConfig.getEurekaServerDNSName();
}
}