Search in sources :

Example 1 with Client

use of com.linkedin.r2.transport.common.Client in project rest.li by linkedin.

the class SimpleLoadBalancer method getClient.

/**
   * Given a Request, returns a TransportClient that can handle requests for the Request.
   *
   *
   * @param request
   *          A request whose URI is a URL of the format "d2://>servicename</optional/path".
   * @param requestContext context for this request
   * @return A client that can be called to retrieve data for the URN.
   * @throws ServiceUnavailableException
   *           If the load balancer can't figure out how to reach a service for the given
   *           URN, an ServiceUnavailableException will be thrown.
   */
@Override
public TransportClient getClient(Request request, RequestContext requestContext) throws ServiceUnavailableException {
    TransportClient client;
    URI uri = request.getURI();
    debug(_log, "get client for uri: ", uri);
    ServiceProperties service = listenToServiceAndCluster(uri);
    String serviceName = service.getServiceName();
    String clusterName = service.getClusterName();
    ClusterProperties cluster = getClusterProperties(serviceName, clusterName);
    // Check if we want to override the service URL and bypass choosing among the existing
    // tracker clients. This is useful when the service we want is not announcing itself to
    // the cluster, ie a private service for a set of clients.
    URI targetService = LoadBalancerUtil.TargetHints.getRequestContextTargetService(requestContext);
    if (targetService == null) {
        LoadBalancerStateItem<UriProperties> uriItem = getUriItem(serviceName, clusterName, cluster);
        UriProperties uris = uriItem.getProperty();
        List<LoadBalancerState.SchemeStrategyPair> orderedStrategies = _state.getStrategiesForService(serviceName, service.getPrioritizedSchemes());
        TrackerClient trackerClient = chooseTrackerClient(request, requestContext, serviceName, clusterName, cluster, uriItem, uris, orderedStrategies, service);
        String clusterAndServiceUriString = trackerClient.getUri() + service.getPath();
        client = new RewriteClient(serviceName, URI.create(clusterAndServiceUriString), trackerClient);
        _serviceAvailableStats.inc();
    } else {
        _log.debug("service hint found, using generic client for target: {}", targetService);
        TransportClient transportClient = _state.getClient(serviceName, targetService.getScheme());
        client = new RewriteClient(serviceName, targetService, transportClient);
    }
    return client;
}
Also used : ServiceProperties(com.linkedin.d2.balancer.properties.ServiceProperties) TransportClient(com.linkedin.r2.transport.common.bridge.client.TransportClient) TrackerClient(com.linkedin.d2.balancer.clients.TrackerClient) UriProperties(com.linkedin.d2.balancer.properties.UriProperties) ClusterProperties(com.linkedin.d2.balancer.properties.ClusterProperties) URI(java.net.URI) RewriteClient(com.linkedin.d2.balancer.clients.RewriteClient)

Example 2 with Client

use of com.linkedin.r2.transport.common.Client in project rest.li by linkedin.

the class SimpleLoadBalancerState method getClient.

@Override
public TransportClient getClient(String serviceName, String scheme) {
    Map<String, TransportClient> transportClients = _serviceClients.get(serviceName);
    TransportClient transportClient = null;
    if (transportClients != null) {
        transportClient = transportClients.get(scheme.toLowerCase());
        if (transportClient == null) {
            warn(_log, "no generic transport client for service " + serviceName + " and scheme: " + scheme);
        }
    } else {
        warn(_log, "get client called on unknown service ", serviceName);
    }
    return transportClient;
}
Also used : TransportClient(com.linkedin.r2.transport.common.bridge.client.TransportClient)

Example 3 with Client

use of com.linkedin.r2.transport.common.Client in project rest.li by linkedin.

the class SimpleLoadBalancerState method createAndInsertTransportClientTo.

private Map<String, TransportClient> createAndInsertTransportClientTo(ServiceProperties serviceProperties) {
    Map<String, Object> transportClientProperties = new HashMap<String, Object>(serviceProperties.getTransportClientProperties());
    Object allowedClientOverrideKeysObj = transportClientProperties.remove(PropertyKeys.ALLOWED_CLIENT_OVERRIDE_KEYS);
    Set<String> allowedClientOverrideKeys = new HashSet<String>(ConfigValueExtractor.buildList(allowedClientOverrideKeysObj, LIST_SEPARATOR));
    Map<String, Object> clientSuppliedServiceProperties = _clientServicesConfig.get(serviceProperties.getServiceName());
    if (clientSuppliedServiceProperties != null) {
        debug(_log, "Client supplied configs for service {}", new Object[] { serviceProperties.getServiceName() });
        // check for overrides
        for (String clientSuppliedKey : clientSuppliedServiceProperties.keySet()) {
            // clients can only override config properties which have been allowed by the service
            if (allowedClientOverrideKeys.contains(clientSuppliedKey)) {
                if (ClientServiceConfigValidator.isValidValue(transportClientProperties, clientSuppliedServiceProperties, clientSuppliedKey)) {
                    transportClientProperties.put(clientSuppliedKey, clientSuppliedServiceProperties.get(clientSuppliedKey));
                    info(_log, "Client overrode config property {} for service {}. This is being used to instantiate the Transport Client", new Object[] { clientSuppliedKey, serviceProperties.getServiceName() });
                } else {
                    warn(_log, "Client supplied config property {} with an invalid value {} for service {}", new Object[] { clientSuppliedKey, clientSuppliedServiceProperties.get(clientSuppliedKey), serviceProperties.getServiceName() });
                }
            }
        }
    }
    List<String> schemes = serviceProperties.getPrioritizedSchemes();
    Map<String, TransportClient> newTransportClients = new HashMap<String, TransportClient>();
    if (schemes != null && !schemes.isEmpty()) {
        for (String scheme : schemes) {
            TransportClientFactory factory = _clientFactories.get(scheme);
            if ("https".equals(scheme)) {
                if (_isSSLEnabled) {
                    // should have been passed in during creation.
                    if (_sslContext != null && _sslParameters != null) {
                        transportClientProperties.put(HttpClientFactory.HTTP_SSL_CONTEXT, _sslContext);
                        transportClientProperties.put(HttpClientFactory.HTTP_SSL_PARAMS, _sslParameters);
                    } else {
                        _log.error("https specified as a prioritized scheme for service: " + serviceProperties.getServiceName() + " but no SSLContext or SSLParameters have been configured.");
                        if (schemes.size() == 1) {
                            // throw exception when https is the only scheme specified
                            throw new IllegalStateException("SSL enabled but required SSLContext and SSLParameters" + "were not both present.");
                        }
                        // Do not create the transport client for https.
                        continue;
                    }
                } else {
                    // is requested later on, getTrackerClient will catch this situation and log an error.
                    continue;
                }
            }
            if (factory != null) {
                transportClientProperties.put(HttpClientFactory.HTTP_SERVICE_NAME, serviceProperties.getServiceName());
                TransportClient client = factory.getClient(transportClientProperties);
                newTransportClients.put(scheme.toLowerCase(), client);
            } else {
                _log.warn("Failed to find client factory for scheme {}", scheme);
            }
        }
    } else {
        _log.warn("Prioritized schemes is null for service properties = " + serviceProperties.getServiceName());
    }
    return newTransportClients;
}
Also used : TransportClient(com.linkedin.r2.transport.common.bridge.client.TransportClient) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) TransportClientFactory(com.linkedin.r2.transport.common.TransportClientFactory) HashSet(java.util.HashSet)

Example 4 with Client

use of com.linkedin.r2.transport.common.Client in project rest.li by linkedin.

the class SimpleLoadBalancerState method shutdown.

@Override
public void shutdown(final PropertyEventShutdownCallback shutdown) {
    trace(_log, "shutdown");
    // shutdown all three registries, all tracker clients, and the event thread
    _executor.execute(new PropertyEvent("shutdown load balancer state") {

        @Override
        public void innerRun() {
            // Need to shutdown loadBalancerStrategies before the transportClients are shutdown
            for (Map<String, LoadBalancerStrategy> strategyEntry : _serviceStrategies.values()) {
                strategyEntry.values().forEach(LoadBalancerStrategy::shutdown);
            }
            // put all tracker clients into a single set for convenience
            Set<TransportClient> transportClients = new HashSet<TransportClient>();
            for (Map<String, TransportClient> clientsByScheme : _serviceClients.values()) {
                transportClients.addAll(clientsByScheme.values());
            }
            Callback<None> trackerCallback = Callbacks.countDown(Callbacks.<None>adaptSimple(new SimpleCallback() {

                @Override
                public void onDone() {
                    shutdown.done();
                }
            }), transportClients.size());
            info(_log, "shutting down cluster clients");
            for (TransportClient transportClient : transportClients) {
                transportClient.shutdown(trackerCallback);
            }
            // so it is needed to notify all the listeners
            for (SimpleLoadBalancerStateListener listener : _listeners) {
                // Notify the strategy removal
                for (Map.Entry<String, Map<String, LoadBalancerStrategy>> serviceStrategy : _serviceStrategies.entrySet()) {
                    for (Map.Entry<String, LoadBalancerStrategy> strategyEntry : serviceStrategy.getValue().entrySet()) {
                        listener.onStrategyRemoved(serviceStrategy.getKey(), strategyEntry.getKey(), strategyEntry.getValue());
                    }
                    // Also notify the client removal
                    Map<URI, TrackerClient> trackerClients = _trackerClients.get(serviceStrategy.getKey());
                    if (trackerClients != null) {
                        for (TrackerClient client : trackerClients.values()) {
                            listener.onClientRemoved(serviceStrategy.getKey(), client);
                        }
                    }
                }
            }
        }
    });
}
Also used : TransportClient(com.linkedin.r2.transport.common.bridge.client.TransportClient) Set(java.util.Set) HashSet(java.util.HashSet) PropertyEvent(com.linkedin.d2.discovery.event.PropertyEventThread.PropertyEvent) LoadBalancerStrategy(com.linkedin.d2.balancer.strategies.LoadBalancerStrategy) PropertyEventShutdownCallback(com.linkedin.d2.discovery.event.PropertyEventThread.PropertyEventShutdownCallback) Callback(com.linkedin.common.callback.Callback) SimpleCallback(com.linkedin.common.callback.SimpleCallback) TrackerClient(com.linkedin.d2.balancer.clients.TrackerClient) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) ConcurrentMap(java.util.concurrent.ConcurrentMap) None(com.linkedin.common.util.None) SimpleCallback(com.linkedin.common.callback.SimpleCallback)

Example 5 with Client

use of com.linkedin.r2.transport.common.Client in project rest.li by linkedin.

the class RewriteClientTestStreamRequest method testWithEverything.

@Test
public void testWithEverything() {
    URI uri = URI.create("http://username:password@test.linkedin.com:9876/test");
    String serviceName = "HistoryService";
    TestClient wrappedClient = new TestClient();
    RewriteClient client = new RewriteClient(serviceName, uri, wrappedClient);
    assertEquals(client.getUri(), uri);
    assertEquals(client.getServiceName(), serviceName);
    assertEquals(client.getWrappedClient(), wrappedClient);
    StreamRequest streamRequest = getRequest("d2://HistoryService/getCube?bar=baz#fragId");
    Map<String, String> restWireAttrs = new HashMap<String, String>();
    TestTransportCallback<StreamResponse> restCallback = new TestTransportCallback<StreamResponse>();
    client.streamRequest(streamRequest, new RequestContext(), restWireAttrs, restCallback);
    assertFalse(restCallback.response.hasError());
    assertEquals(wrappedClient.streamRequest.getHeaders(), streamRequest.getHeaders());
    assertEquals(wrappedClient.streamRequest.getMethod(), streamRequest.getMethod());
    assertEquals(wrappedClient.streamRequest.getURI(), URI.create("http://username:password@test.linkedin.com:9876/test/getCube?bar=baz#fragId"));
}
Also used : HashMap(java.util.HashMap) TestClient(com.linkedin.d2.balancer.clients.TrackerClientTest.TestClient) TestTransportCallback(com.linkedin.d2.balancer.clients.TrackerClientTest.TestTransportCallback) StreamResponse(com.linkedin.r2.message.stream.StreamResponse) RequestContext(com.linkedin.r2.message.RequestContext) URI(java.net.URI) StreamRequest(com.linkedin.r2.message.stream.StreamRequest) Test(org.testng.annotations.Test)

Aggregations

Test (org.testng.annotations.Test)126 RequestContext (com.linkedin.r2.message.RequestContext)94 URI (java.net.URI)82 RestRequestBuilder (com.linkedin.r2.message.rest.RestRequestBuilder)65 FutureCallback (com.linkedin.common.callback.FutureCallback)62 RestRequest (com.linkedin.r2.message.rest.RestRequest)62 HashMap (java.util.HashMap)61 RestResponse (com.linkedin.r2.message.rest.RestResponse)48 StreamResponse (com.linkedin.r2.message.stream.StreamResponse)44 ArrayList (java.util.ArrayList)37 None (com.linkedin.common.util.None)36 Client (com.linkedin.r2.transport.common.Client)36 TransportClient (com.linkedin.r2.transport.common.bridge.client.TransportClient)36 StreamRequest (com.linkedin.r2.message.stream.StreamRequest)35 CountDownLatch (java.util.concurrent.CountDownLatch)35 TrackerClient (com.linkedin.d2.balancer.clients.TrackerClient)34 StreamRequestBuilder (com.linkedin.r2.message.stream.StreamRequestBuilder)33 ExecutionException (java.util.concurrent.ExecutionException)33 RemoteInvocationException (com.linkedin.r2.RemoteInvocationException)26 TransportClientFactory (com.linkedin.r2.transport.common.TransportClientFactory)26