use of com.netflix.util.Pair 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.util.Pair 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;
}
Aggregations