use of com.netflix.client.ClientException in project ribbon by Netflix.
the class LoadBalancerContext method getServerFromLoadBalancer.
/**
* Compute the final URI from a partial URI in the request. The following steps are performed:
* <ul>
* <li> if host is missing and there is a load balancer, get the host/port from server chosen from load balancer
* <li> if host is missing and there is no load balancer, try to derive host/port from virtual address set with the client
* <li> if host is present and the authority part of the URI is a virtual address set for the client,
* and there is a load balancer, get the host/port from server chosen from load balancer
* <li> if host is present but none of the above applies, interpret the host as the actual physical address
* <li> if host is missing but none of the above applies, throws ClientException
* </ul>
*
* @param original Original URI passed from caller
*/
public Server getServerFromLoadBalancer(@Nullable URI original, @Nullable Object loadBalancerKey) throws ClientException {
String host = null;
int port = -1;
if (original != null) {
host = original.getHost();
}
if (original != null) {
Pair<String, Integer> schemeAndPort = deriveSchemeAndPortFromPartialUri(original);
port = schemeAndPort.second();
}
// Various Supported Cases
// The loadbalancer to use and the instances it has is based on how it was registered
// In each of these cases, the client might come in using Full Url or Partial URL
ILoadBalancer lb = getLoadBalancer();
if (host == null) {
// well we have to just get the right instances from lb - or we fall back
if (lb != null) {
Server svc = lb.chooseServer(loadBalancerKey);
if (svc == null) {
throw new ClientException(ClientException.ErrorType.GENERAL, "Load balancer does not have available server for client: " + clientName);
}
host = svc.getHost();
if (host == null) {
throw new ClientException(ClientException.ErrorType.GENERAL, "Invalid Server for :" + svc);
}
logger.debug("{} using LB returned Server: {} for request {}", new Object[] { clientName, svc, original });
return svc;
} else {
// bail out
if (vipAddresses != null && vipAddresses.contains(",")) {
throw new ClientException(ClientException.ErrorType.GENERAL, "Method is invoked for client " + clientName + " with partial URI of (" + original + ") with no load balancer configured." + " Also, there are multiple vipAddresses and hence no vip address can be chosen" + " to complete this partial uri");
} else if (vipAddresses != null) {
try {
Pair<String, Integer> hostAndPort = deriveHostAndPortFromVipAddress(vipAddresses);
host = hostAndPort.first();
port = hostAndPort.second();
} catch (URISyntaxException e) {
throw new ClientException(ClientException.ErrorType.GENERAL, "Method is invoked for client " + clientName + " with partial URI of (" + original + ") with no load balancer configured. " + " Also, the configured/registered vipAddress is unparseable (to determine host and port)");
}
} else {
throw new ClientException(ClientException.ErrorType.GENERAL, this.clientName + " has no LoadBalancer registered and passed in a partial URL request (with no host:port)." + " Also has no vipAddress registered");
}
}
} else {
// Full URL Case
// This could either be a vipAddress or a hostAndPort or a real DNS
// if vipAddress or hostAndPort, we just have to consult the loadbalancer
// but if it does not return a server, we should just proceed anyways
// and assume its a DNS
// For restClients registered using a vipAddress AND executing a request
// by passing in the full URL (including host and port), we should only
// consult lb IFF the URL passed is registered as vipAddress in Discovery
boolean shouldInterpretAsVip = false;
if (lb != null) {
shouldInterpretAsVip = isVipRecognized(original.getAuthority());
}
if (shouldInterpretAsVip) {
Server svc = lb.chooseServer(loadBalancerKey);
if (svc != null) {
host = svc.getHost();
if (host == null) {
throw new ClientException(ClientException.ErrorType.GENERAL, "Invalid Server for :" + svc);
}
logger.debug("using LB returned Server: {} for request: {}", svc, original);
return svc;
} else {
// just fall back as real DNS
logger.debug("{}:{} assumed to be a valid VIP address or exists in the DNS", host, port);
}
} else {
// consult LB to obtain vipAddress backed instance given full URL
//Full URL execute request - where url!=vipAddress
logger.debug("Using full URL passed in by caller (not using load balancer): {}", original);
}
}
// end of creating final URL
if (host == null) {
throw new ClientException(ClientException.ErrorType.GENERAL, "Request contains no HOST to talk to");
}
return new Server(host, port);
}
use of com.netflix.client.ClientException in project ribbon by Netflix.
the class LoadBalancerContext method deriveHostAndPortFromVipAddress.
/**
* Derive the host and port from virtual address if virtual address is indeed contains the actual host
* and port of the server. This is the final resort to compute the final URI in {@link #getServerFromLoadBalancer(java.net.URI, Object)}
* if there is no load balancer available and the request URI is incomplete. Sub classes can override this method
* to be more accurate or throws ClientException if it does not want to support virtual address to be the
* same as physical server address.
* <p>
* The virtual address is used by certain load balancers to filter the servers of the same function
* to form the server pool.
*
*/
protected Pair<String, Integer> deriveHostAndPortFromVipAddress(String vipAddress) throws URISyntaxException, ClientException {
Pair<String, Integer> hostAndPort = new Pair<String, Integer>(null, -1);
URI uri = new URI(vipAddress);
String scheme = uri.getScheme();
if (scheme == null) {
uri = new URI("http://" + vipAddress);
}
String host = uri.getHost();
if (host == null) {
throw new ClientException("Unable to derive host/port from vip address " + vipAddress);
}
int port = uri.getPort();
if (port < 0) {
port = getDefaultPortFromScheme(scheme);
}
if (port < 0) {
throw new ClientException("Unable to derive host/port from vip address " + vipAddress);
}
hostAndPort.setFirst(host);
hostAndPort.setSecond(port);
return hostAndPort;
}
use of com.netflix.client.ClientException in project ribbon by Netflix.
the class RestClient method execute.
private HttpResponse execute(HttpRequest.Verb verb, URI uri, Map<String, Collection<String>> headers, Map<String, Collection<String>> params, IClientConfig overriddenClientConfig, Object requestEntity) throws Exception {
HttpClientResponse thisResponse = null;
boolean bbFollowRedirects = bFollowRedirects;
// read overriden props
if (overriddenClientConfig != null && // set whether we should auto follow redirects
overriddenClientConfig.getProperty(CommonClientConfigKey.FollowRedirects) != null) {
// use default directive from overall config
Boolean followRedirects = Boolean.valueOf("" + overriddenClientConfig.getProperty(CommonClientConfigKey.FollowRedirects, bFollowRedirects));
bbFollowRedirects = followRedirects.booleanValue();
}
restClient.setFollowRedirects(bbFollowRedirects);
if (logger.isDebugEnabled()) {
logger.debug("RestClient sending new Request(" + verb + ": ) " + uri);
}
WebResource xResource = restClient.resource(uri.toString());
if (params != null) {
for (Map.Entry<String, Collection<String>> entry : params.entrySet()) {
String name = entry.getKey();
for (String value : entry.getValue()) {
xResource = xResource.queryParam(name, value);
}
}
}
ClientResponse jerseyResponse;
Builder b = xResource.getRequestBuilder();
if (headers != null) {
for (Map.Entry<String, Collection<String>> entry : headers.entrySet()) {
String name = entry.getKey();
for (String value : entry.getValue()) {
b = b.header(name, value);
}
}
}
Object entity = requestEntity;
switch(verb) {
case GET:
jerseyResponse = b.get(ClientResponse.class);
break;
case POST:
jerseyResponse = b.post(ClientResponse.class, entity);
break;
case PUT:
jerseyResponse = b.put(ClientResponse.class, entity);
break;
case DELETE:
jerseyResponse = b.delete(ClientResponse.class);
break;
case HEAD:
jerseyResponse = b.head();
break;
case OPTIONS:
jerseyResponse = b.options(ClientResponse.class);
break;
default:
throw new ClientException(ClientException.ErrorType.GENERAL, "You have to one of the REST verbs such as GET, POST etc.");
}
thisResponse = new HttpClientResponse(jerseyResponse, uri, overriddenClientConfig);
if (thisResponse.getStatus() == 503) {
thisResponse.close();
throw new ClientException(ClientException.ErrorType.SERVER_THROTTLED);
}
return thisResponse;
}
use of com.netflix.client.ClientException in project ribbon by Netflix.
the class RetryTest method postReadTimeout.
@Test
public void postReadTimeout() throws Exception {
URI localUrl = new URI("/noresponse");
HttpRequest request = HttpRequest.newBuilder().uri(localUrl).verb(Verb.POST).build();
try {
client.executeWithLoadBalancer(request, DefaultClientConfigImpl.getEmptyConfig().set(CommonClientConfigKey.MaxAutoRetriesNextServer, 2));
fail("Exception expected");
} catch (ClientException e) {
// NOPMD
}
ServerStats stats = lb.getLoadBalancerStats().getSingleServerStat(localServer);
assertEquals(1, stats.getSuccessiveConnectionFailureCount());
}
use of com.netflix.client.ClientException in project ribbon by Netflix.
the class RetryTest method testReadTimeoutWithRetriesNextServe.
@Test
public void testReadTimeoutWithRetriesNextServe() throws Exception {
URI localUrl = new URI("/noresponse");
HttpRequest request = HttpRequest.newBuilder().uri(localUrl).build();
try {
client.executeWithLoadBalancer(request, DefaultClientConfigImpl.getEmptyConfig().set(CommonClientConfigKey.MaxAutoRetriesNextServer, 2));
fail("Exception expected");
} catch (ClientException e) {
// NOPMD
}
assertEquals(3, lb.getLoadBalancerStats().getSingleServerStat(localServer).getSuccessiveConnectionFailureCount());
}
Aggregations