Search in sources :

Example 16 with ClientException

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);
}
Also used : ClientException(com.netflix.client.ClientException) URISyntaxException(java.net.URISyntaxException) Pair(com.netflix.util.Pair)

Example 17 with ClientException

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;
}
Also used : ClientException(com.netflix.client.ClientException) URI(java.net.URI) Pair(com.netflix.util.Pair)

Example 18 with ClientException

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;
}
Also used : ClientResponse(com.sun.jersey.api.client.ClientResponse) Builder(com.sun.jersey.api.client.WebResource.Builder) WebResource(com.sun.jersey.api.client.WebResource) Collection(java.util.Collection) ClientException(com.netflix.client.ClientException) Map(java.util.Map)

Example 19 with ClientException

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());
}
Also used : HttpRequest(com.netflix.client.http.HttpRequest) ServerStats(com.netflix.loadbalancer.ServerStats) ClientException(com.netflix.client.ClientException) URI(java.net.URI) Test(org.junit.Test)

Example 20 with ClientException

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());
}
Also used : HttpRequest(com.netflix.client.http.HttpRequest) ClientException(com.netflix.client.ClientException) URI(java.net.URI) Test(org.junit.Test)

Aggregations

ClientException (com.netflix.client.ClientException)24 Test (org.junit.Test)18 URI (java.net.URI)11 HttpRequest (com.netflix.client.http.HttpRequest)9 Server (com.netflix.loadbalancer.Server)8 ServerStats (com.netflix.loadbalancer.ServerStats)7 MockWebServer (com.google.mockwebserver.MockWebServer)6 ByteBuf (io.netty.buffer.ByteBuf)6 IClientConfig (com.netflix.client.config.IClientConfig)5 AvailabilityFilteringRule (com.netflix.loadbalancer.AvailabilityFilteringRule)5 BaseLoadBalancer (com.netflix.loadbalancer.BaseLoadBalancer)5 DummyPing (com.netflix.loadbalancer.DummyPing)5 HttpServer (com.sun.net.httpserver.HttpServer)4 IOException (java.io.IOException)4 AbortExecutionException (com.netflix.loadbalancer.reactive.ExecutionListener.AbortExecutionException)3 HttpResponse (com.netflix.client.http.HttpResponse)2 ExecutionListener (com.netflix.loadbalancer.reactive.ExecutionListener)2 Person (com.netflix.ribbon.test.resources.EmbeddedResources.Person)2 Pair (com.netflix.util.Pair)2 HttpClientResponse (io.reactivex.netty.protocol.http.client.HttpClientResponse)2