package com.netflix.discovery.shared.resolver.aws; import com.netflix.appinfo.InstanceInfo; import com.netflix.discovery.EurekaClientConfig; import com.netflix.discovery.EurekaClientNames; import com.netflix.discovery.shared.Applications; import com.netflix.discovery.shared.resolver.ClusterResolver; import com.netflix.discovery.shared.resolver.EurekaEndpoint; import com.netflix.discovery.shared.resolver.ResolverUtils; import com.netflix.discovery.shared.transport.EurekaHttpClient; import com.netflix.discovery.shared.transport.EurekaHttpClientFactory; import com.netflix.discovery.shared.transport.EurekaHttpResponse; import com.netflix.discovery.shared.transport.EurekaTransportConfig; import com.netflix.discovery.shared.transport.TransportClientFactory; import com.netflix.discovery.shared.transport.decorator.RetryableEurekaHttpClient; import com.netflix.discovery.shared.transport.decorator.ServerStatusEvaluators; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * @author David Liu */ public class EurekaHttpResolver implements ClusterResolver<AwsEndpoint> { private static final Logger logger = LoggerFactory.getLogger(EurekaHttpResolver.class); private final EurekaClientConfig clientConfig; private final EurekaTransportConfig transportConfig; private final String vipAddress; private final EurekaHttpClientFactory clientFactory; public EurekaHttpResolver(EurekaClientConfig clientConfig, EurekaTransportConfig transportConfig, ClusterResolver<EurekaEndpoint> bootstrapResolver, TransportClientFactory transportClientFactory, String vipAddress) { this( clientConfig, transportConfig, RetryableEurekaHttpClient.createFactory( EurekaClientNames.RESOLVER, transportConfig, bootstrapResolver, transportClientFactory, ServerStatusEvaluators.httpSuccessEvaluator() ), vipAddress ); } /* visible for testing */ EurekaHttpResolver(EurekaClientConfig clientConfig, EurekaTransportConfig transportConfig, EurekaHttpClientFactory clientFactory, String vipAddress) { this.clientConfig = clientConfig; this.transportConfig = transportConfig; this.clientFactory = clientFactory; this.vipAddress = vipAddress; } @Override public String getRegion() { return clientConfig.getRegion(); } @Override public List<AwsEndpoint> getClusterEndpoints() { List<AwsEndpoint> result = new ArrayList<>(); EurekaHttpClient client = null; try { client = clientFactory.newClient(); EurekaHttpResponse<Applications> response = client.getVip(vipAddress); if (validResponse(response)) { Applications applications = response.getEntity(); if (applications != null) { applications.shuffleInstances(true); // filter out non-UP instances List<InstanceInfo> validInstanceInfos = applications.getInstancesByVirtualHostName(vipAddress); for (InstanceInfo instanceInfo : validInstanceInfos) { AwsEndpoint endpoint = ResolverUtils.instanceInfoToEndpoint(clientConfig, transportConfig, instanceInfo); if (endpoint != null) { result.add(endpoint); } } logger.debug("Retrieved endpoint list {}", result); return result; } } } catch (Exception e) { logger.error("Error contacting server for endpoints with vipAddress:{}", vipAddress, e); } finally { if (client != null) { client.shutdown(); } } logger.info("Returning empty endpoint list"); return Collections.emptyList(); } private <T> boolean validResponse(EurekaHttpResponse<T> response) { if (response == null) { return false; } int responseCode = response.getStatusCode(); return responseCode >= 200 && responseCode < 300; } }