use of com.netflix.discovery.shared.transport.TransportException in project eureka by Netflix.
the class RetryableEurekaHttpClient method execute.
@Override
protected <R> EurekaHttpResponse<R> execute(RequestExecutor<R> requestExecutor) {
List<EurekaEndpoint> candidateHosts = null;
int endpointIdx = 0;
for (int retry = 0; retry < numberOfRetries; retry++) {
EurekaHttpClient currentHttpClient = delegate.get();
EurekaEndpoint currentEndpoint = null;
if (currentHttpClient == null) {
if (candidateHosts == null) {
candidateHosts = getHostCandidates();
if (candidateHosts.isEmpty()) {
throw new TransportException("There is no known eureka server; cluster server list is empty");
}
}
if (endpointIdx >= candidateHosts.size()) {
throw new TransportException("Cannot execute request on any known server");
}
currentEndpoint = candidateHosts.get(endpointIdx++);
currentHttpClient = clientFactory.newClient(currentEndpoint);
}
try {
EurekaHttpResponse<R> response = requestExecutor.execute(currentHttpClient);
if (serverStatusEvaluator.accept(response.getStatusCode(), requestExecutor.getRequestType())) {
delegate.set(currentHttpClient);
if (retry > 0) {
logger.info("Request execution succeeded on retry #{}", retry);
}
return response;
}
logger.warn("Request execution failure with status code {}; retrying on another server if available", response.getStatusCode());
} catch (Exception e) {
// just log message as the underlying client should log the stacktrace
logger.warn("Request execution failed with message: {}", e.getMessage());
}
// Connection error or 5xx from the server that must be retried on another server
delegate.compareAndSet(currentHttpClient, null);
if (currentEndpoint != null) {
quarantineSet.add(currentEndpoint);
}
}
throw new TransportException("Retry limit reached; giving up on completing the request");
}
use of com.netflix.discovery.shared.transport.TransportException in project eureka by Netflix.
the class RedirectingEurekaHttpClient method executeOnNewServer.
private <R> EurekaHttpResponse<R> executeOnNewServer(RequestExecutor<R> requestExecutor, AtomicReference<EurekaHttpClient> currentHttpClientRef) {
URI targetUrl = null;
for (int followRedirectCount = 0; followRedirectCount < MAX_FOLLOWED_REDIRECTS; followRedirectCount++) {
EurekaHttpResponse<R> httpResponse = requestExecutor.execute(currentHttpClientRef.get());
if (httpResponse.getStatusCode() != 302) {
if (followRedirectCount == 0) {
logger.debug("Pinning to endpoint {}", targetUrl);
} else {
logger.info("Pinning to endpoint {}, after {} redirect(s)", targetUrl, followRedirectCount);
}
return httpResponse;
}
targetUrl = getRedirectBaseUri(httpResponse.getLocation());
if (targetUrl == null) {
throw new TransportException("Invalid redirect URL " + httpResponse.getLocation());
}
currentHttpClientRef.getAndSet(null).shutdown();
currentHttpClientRef.set(factory.newClient(new DefaultEndpoint(targetUrl.toString())));
}
String message = "Follow redirect limit crossed for URI " + serviceEndpoint.getServiceUrl();
logger.warn(message);
throw new TransportException(message);
}
use of com.netflix.discovery.shared.transport.TransportException in project eureka by Netflix.
the class RedirectingEurekaHttpClientTest method testOnConnectionErrorPinnedClientIsDestroyed.
@Test
public void testOnConnectionErrorPinnedClientIsDestroyed() throws Exception {
setupRedirect();
RedirectingEurekaHttpClient httpClient = new RedirectingEurekaHttpClient(SERVICE_URL, factory, dnsService);
// First call pins client to resolved IP
httpClient.getApplications();
verify(redirectedClient, times(1)).getApplications();
// Trigger connection error
when(redirectedClient.getApplications()).thenThrow(new TransportException("simulated network error"));
try {
httpClient.getApplications();
fail("Expected transport error");
} catch (Exception ignored) {
}
// Subsequent connection shall create new httpClient
reset(factory, sourceClient, dnsService, redirectedClient);
setupRedirect();
httpClient.getApplications();
verify(factory, times(2)).newClient(Matchers.<EurekaEndpoint>anyVararg());
verify(sourceClient, times(1)).getApplications();
verify(dnsService, times(1)).resolveIp("another.discovery.test");
verify(redirectedClient, times(1)).getApplications();
}
use of com.netflix.discovery.shared.transport.TransportException in project eureka by Netflix.
the class RedirectingEurekaHttpClient method getRedirectBaseUri.
private URI getRedirectBaseUri(URI locationURI) {
if (locationURI == null) {
throw new TransportException("Missing Location header in the redirect reply");
}
Matcher pathMatcher = REDIRECT_PATH_REGEX.matcher(locationURI.getPath());
if (pathMatcher.matches()) {
return UriBuilder.fromUri(locationURI).host(dnsService.resolveIp(locationURI.getHost())).replacePath(pathMatcher.group(1)).replaceQuery(null).build();
}
logger.warn("Invalid redirect URL {}", locationURI);
return null;
}
use of com.netflix.discovery.shared.transport.TransportException in project eureka by Netflix.
the class RetryableEurekaHttpClientTest method testRequestIsRetriedOnConnectionError.
@Test
public void testRequestIsRetriedOnConnectionError() throws Exception {
when(clientFactory.newClient(Matchers.<EurekaEndpoint>anyVararg())).thenReturn(clusterDelegates.get(0), clusterDelegates.get(1));
when(requestExecutor.execute(clusterDelegates.get(0))).thenThrow(new TransportException("simulated network error"));
when(requestExecutor.execute(clusterDelegates.get(1))).thenReturn(EurekaHttpResponse.status(200));
EurekaHttpResponse<Void> httpResponse = retryableClient.execute(requestExecutor);
assertThat(httpResponse.getStatusCode(), is(equalTo(200)));
verify(clientFactory, times(2)).newClient(Matchers.<EurekaEndpoint>anyVararg());
verify(requestExecutor, times(1)).execute(clusterDelegates.get(0));
verify(requestExecutor, times(1)).execute(clusterDelegates.get(1));
}
Aggregations