Search in sources :

Example 81 with Client

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

the class LoadBalancerEchoClient method startClient.

public void startClient() throws URISyntaxException, InterruptedException, ExecutionException, IOException, PropertyStoreException {
    DynamicClient client = new DynamicClient(getLoadBalancer(_hostPort), null);
    for (; ; ) {
        int index = 0;
        if (_services.length > 1) {
            index = _random.nextInt(_services.length);
        }
        String service = _services[index];
        URI uri = URI.create("d2://" + service);
        RestRequest req = new RestRequestBuilder(uri).setEntity("hi there".getBytes("UTF-8")).build();
        try {
            Future<RestResponse> response = client.restRequest(req);
            String responseString = response.get().getEntity().asString("UTF-8");
            System.err.println(uri + " response: " + responseString);
        } catch (ExecutionException e) {
            System.err.println("future.get() failed for " + uri + ": " + e);
        }
        Thread.sleep(_random.nextInt(1000));
    }
}
Also used : RestRequest(com.linkedin.r2.message.rest.RestRequest) RestResponse(com.linkedin.r2.message.rest.RestResponse) DynamicClient(com.linkedin.d2.balancer.clients.DynamicClient) RestRequestBuilder(com.linkedin.r2.message.rest.RestRequestBuilder) ExecutionException(java.util.concurrent.ExecutionException) URI(java.net.URI)

Example 82 with Client

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

the class DegraderLoadBalancerTest method simulateAndTestOneInterval.

/**
   * simulates calling all the clients with the given QPS according to the given interval.
   * Then verify that the DegraderLoadBalancerState behaves as expected.
   * @param expectedPointsPerClient we'll verify if the points are smaller than the number given here
   * @param isCalledWithError
   * @param isCalledWithErrorForLoadBalancing
   */
private TrackerClient simulateAndTestOneInterval(long timeInterval, TestClock clock, double qps, List<TrackerClient> clients, DegraderLoadBalancerStrategyAdapter adapter, long clusterGenerationId, Integer expectedPointsPerClient, boolean isExpectingDropCallStrategyForNewState, double expectedClusterOverrideDropRate, long latency, boolean isCalledWithError, boolean isCalledWithErrorForLoadBalancing) {
    callClients(latency, qps, clients, clock, timeInterval, isCalledWithError, isCalledWithErrorForLoadBalancing);
    //create any random URIRequest because we just need a URI to be hashed to get the point in hash ring anyway
    if (clients != null && !clients.isEmpty()) {
        URIRequest request = new URIRequest(clients.get(0).getUri());
        TrackerClient client = getTrackerClient(adapter, request, new RequestContext(), clusterGenerationId, clients);
        Map<URI, Integer> pointsMap = adapter.getPointsMap();
        for (TrackerClient trackerClient : clients) {
            Integer pointsInTheRing = pointsMap.get(trackerClient.getUri());
            assertEquals(pointsInTheRing, expectedPointsPerClient);
        }
        if (isExpectingDropCallStrategyForNewState) {
            assertTrue(adapter.isStrategyCallDrop());
        } else {
            assertFalse(adapter.isStrategyCallDrop());
        }
        assertEquals(adapter.getCurrentOverrideDropRate(), expectedClusterOverrideDropRate);
        return client;
    }
    return null;
}
Also used : TrackerClient(com.linkedin.d2.balancer.clients.TrackerClient) URIRequest(com.linkedin.d2.balancer.util.URIRequest) RequestContext(com.linkedin.r2.message.RequestContext) URI(java.net.URI)

Example 83 with Client

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

the class TestMIMEChainingAlternate method testAlternateSinglePartDataSource.

//This test has the server alternate between consuming a part and sending a part as a data source
//to a writer.
//Since we have four parts, the server will consume the 2nd and 4th and send out the 1st and 3rd.
//To make the test easier we will have two callbacks to send to the server to indicate
//the presence of each data source.
//This violates the typical client/server http pattern, but accomplishes the purpose of this test
//and it makes it easier to write.
@Test(dataProvider = "chunkSizes")
public void testAlternateSinglePartDataSource(final int chunkSize) throws Exception {
    final List<MultiPartMIMEDataSourceWriter> dataSources = generateInputStreamDataSources(chunkSize, _scheduledExecutorService);
    final MultiPartMIMEWriter writer = new MultiPartMIMEWriter.Builder().appendDataSources(dataSources).build();
    final StreamRequest streamRequest = mock(StreamRequest.class);
    when(streamRequest.getEntityStream()).thenReturn(writer.getEntityStream());
    final String contentTypeHeader = "multipart/mixed; boundary=" + writer.getBoundary();
    when(streamRequest.getHeader(MultiPartMIMEUtils.CONTENT_TYPE_HEADER)).thenReturn(contentTypeHeader);
    //Client side preparation to read the part back on the callback.
    //We have two callbacks here since we will get two responses.
    //Note the chunks size will carry over since the client is controlling how much data he gets back
    //based on the chunk size he writes.
    MIMETestUtils.MultiPartMIMEFullReaderCallback clientReceiverA = new MIMETestUtils.MultiPartMIMEFullReaderCallback();
    MIMETestUtils.MultiPartMIMEFullReaderCallback clientReceiverB = new MIMETestUtils.MultiPartMIMEFullReaderCallback();
    Callback<StreamResponse> callbackA = generateSuccessChainCallback(clientReceiverA);
    Callback<StreamResponse> callbackB = generateSuccessChainCallback(clientReceiverB);
    //Server side start
    MultiPartMIMEReader reader = MultiPartMIMEReader.createAndAcquireStream(streamRequest);
    final CountDownLatch latch = new CountDownLatch(1);
    ServerMultiPartMIMEAlternatorCallback serverSender = new ServerMultiPartMIMEAlternatorCallback(latch, callbackA, callbackB);
    reader.registerReaderCallback(serverSender);
    latch.await(_testTimeout, TimeUnit.MILLISECONDS);
    //Verify client
    Assert.assertEquals(clientReceiverA.getSinglePartMIMEReaderCallbacks().size(), 1);
    Assert.assertEquals(clientReceiverA.getSinglePartMIMEReaderCallbacks().get(0).getFinishedData(), BODY_A.getPartData());
    Assert.assertEquals(clientReceiverA.getSinglePartMIMEReaderCallbacks().get(0).getHeaders(), BODY_A.getPartHeaders());
    Assert.assertEquals(clientReceiverB.getSinglePartMIMEReaderCallbacks().size(), 1);
    Assert.assertEquals(clientReceiverB.getSinglePartMIMEReaderCallbacks().get(0).getFinishedData(), BODY_C.getPartData());
    Assert.assertEquals(clientReceiverB.getSinglePartMIMEReaderCallbacks().get(0).getHeaders(), BODY_C.getPartHeaders());
    //Verify server
    Assert.assertEquals(serverSender.getSinglePartMIMEReaderCallbacks().size(), 2);
    Assert.assertEquals(serverSender.getSinglePartMIMEReaderCallbacks().get(0).getFinishedData(), BODY_B.getPartData());
    Assert.assertEquals(serverSender.getSinglePartMIMEReaderCallbacks().get(0).getHeaders(), BODY_B.getPartHeaders());
    Assert.assertEquals(serverSender.getSinglePartMIMEReaderCallbacks().get(1).getFinishedData(), BODY_D.getPartData());
    Assert.assertEquals(serverSender.getSinglePartMIMEReaderCallbacks().get(1).getHeaders(), BODY_D.getPartHeaders());
}
Also used : StreamResponse(com.linkedin.r2.message.stream.StreamResponse) CountDownLatch(java.util.concurrent.CountDownLatch) StreamRequest(com.linkedin.r2.message.stream.StreamRequest) MIMETestUtils(com.linkedin.multipart.utils.MIMETestUtils) Test(org.testng.annotations.Test)

Example 84 with Client

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

the class TestMIMEChainingSinglePart method testSinglePartDataSource.

//Verifies that a single part mime reader can be used as a data source to the writer.
//To make the test easier to write, we simply chain back to the client in the form of simulating a response.
@Test(dataProvider = "chunkSizes")
public void testSinglePartDataSource(final int chunkSize) throws Exception {
    final List<MultiPartMIMEDataSourceWriter> dataSources = generateInputStreamDataSources(chunkSize, _scheduledExecutorService);
    final MultiPartMIMEWriter writer = new MultiPartMIMEWriter.Builder().appendDataSources(dataSources).build();
    final StreamRequest streamRequest = mock(StreamRequest.class);
    when(streamRequest.getEntityStream()).thenReturn(writer.getEntityStream());
    final String contentTypeHeader = "multipart/mixed; boundary=" + writer.getBoundary();
    when(streamRequest.getHeader(MultiPartMIMEUtils.CONTENT_TYPE_HEADER)).thenReturn(contentTypeHeader);
    //Client side preparation to read the part back on the callback
    //Note the chunks size will carry over since the client is controlling how much data he gets back
    //based on the chunk size he writes.
    MIMETestUtils.MultiPartMIMEFullReaderCallback clientReceiver = new MIMETestUtils.MultiPartMIMEFullReaderCallback();
    Callback<StreamResponse> callback = generateSuccessChainCallback(clientReceiver);
    //Server side start
    MultiPartMIMEReader reader = MultiPartMIMEReader.createAndAcquireStream(streamRequest);
    final CountDownLatch latch = new CountDownLatch(1);
    ServerMultiPartMIMEReaderSinglePartSenderCallback serverSender = new ServerMultiPartMIMEReaderSinglePartSenderCallback(latch, callback);
    reader.registerReaderCallback(serverSender);
    latch.await(_testTimeout, TimeUnit.MILLISECONDS);
    //Verify client
    Assert.assertEquals(clientReceiver.getSinglePartMIMEReaderCallbacks().size(), 1);
    Assert.assertEquals(clientReceiver.getSinglePartMIMEReaderCallbacks().get(0).getFinishedData(), BODY_A.getPartData());
    Assert.assertEquals(clientReceiver.getSinglePartMIMEReaderCallbacks().get(0).getHeaders(), BODY_A.getPartHeaders());
    //Verify server
    List<MIMETestUtils.SinglePartMIMEFullReaderCallback> singlePartMIMEReaderCallbacks = serverSender.getSinglePartMIMEReaderCallbacks();
    Assert.assertEquals(singlePartMIMEReaderCallbacks.size(), 3);
    Assert.assertEquals(singlePartMIMEReaderCallbacks.get(0).getFinishedData(), BODY_B.getPartData());
    Assert.assertEquals(singlePartMIMEReaderCallbacks.get(0).getHeaders(), BODY_B.getPartHeaders());
    Assert.assertEquals(singlePartMIMEReaderCallbacks.get(1).getFinishedData(), BODY_C.getPartData());
    Assert.assertEquals(singlePartMIMEReaderCallbacks.get(1).getHeaders(), BODY_C.getPartHeaders());
    Assert.assertEquals(singlePartMIMEReaderCallbacks.get(2).getFinishedData(), BODY_D.getPartData());
    Assert.assertEquals(singlePartMIMEReaderCallbacks.get(2).getHeaders(), BODY_D.getPartHeaders());
}
Also used : StreamResponse(com.linkedin.r2.message.stream.StreamResponse) CountDownLatch(java.util.concurrent.CountDownLatch) StreamRequest(com.linkedin.r2.message.stream.StreamRequest) SinglePartMIMEFullReaderCallback(com.linkedin.multipart.utils.MIMETestUtils.SinglePartMIMEFullReaderCallback) MIMETestUtils(com.linkedin.multipart.utils.MIMETestUtils) Test(org.testng.annotations.Test)

Example 85 with Client

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

the class HttpClientFactory method getClient.

/**
   * Create a new {@link TransportClient} with the specified properties,
   * {@link SSLContext} and {@link SSLParameters}
   *
   * @param properties map of properties for the {@link TransportClient}
   * @param sslContext {@link SSLContext} to be used for requests over SSL/TLS.
   * @param sslParameters {@link SSLParameters} to configure secure connections.
   * @return an appropriate {@link TransportClient} instance, as specified by the properties.
   */
private TransportClient getClient(Map<String, ? extends Object> properties, SSLContext sslContext, SSLParameters sslParameters) {
    LOG.info("Getting a client with configuration {} and SSLContext {}", properties, sslContext);
    TransportClient client = getRawClient(properties, sslContext, sslParameters);
    List<String> httpRequestServerSupportedEncodings = ConfigValueExtractor.buildList(properties.remove(HTTP_REQUEST_CONTENT_ENCODINGS), LIST_SEPARATOR);
    // In the old model, responses were compressed according to the type of method, so clients would send
    // the Accept-Encoding header if the method was in HTTP_RESPONSE_COMPRESSION_OPERATIONS.
    // In the new model, responses are compressed according to its size, so clients send the Accept-Encoding header
    // if the server enabled response compression by setting HTTP_USE_RESPONSE_COMPRESSION to true.
    // Until all servers migrate to the new model, clients will understand both models,
    // and send the Accept-Encoding header if either the old or the new criterion is satisfied.
    List<String> httpResponseCompressionOperations = ConfigValueExtractor.buildList(properties.remove(HTTP_RESPONSE_COMPRESSION_OPERATIONS), LIST_SEPARATOR);
    String useResponseCompressionProperty = (String) properties.get(HTTP_USE_RESPONSE_COMPRESSION);
    if (useResponseCompressionProperty != null && Boolean.parseBoolean(useResponseCompressionProperty)) {
        httpResponseCompressionOperations.add(ClientCompressionHelper.COMPRESS_ALL_RESPONSES_INDICATOR);
    }
    FilterChain filters = _filters;
    if (_useClientCompression) {
        List<String> responseEncodings = null;
        if (properties.containsKey(HTTP_RESPONSE_CONTENT_ENCODINGS)) {
            responseEncodings = ConfigValueExtractor.buildList(properties.remove(HTTP_RESPONSE_CONTENT_ENCODINGS), LIST_SEPARATOR);
        }
        String httpServiceName = (String) properties.get(HTTP_SERVICE_NAME);
        EncodingType restRequestContentEncoding = getRestRequestContentEncoding(httpRequestServerSupportedEncodings);
        StreamEncodingType streamRequestContentEncoding = getStreamRequestContentEncoding(httpRequestServerSupportedEncodings);
        if (restRequestContentEncoding != EncodingType.IDENTITY || !httpResponseCompressionOperations.isEmpty()) {
            filters = filters.addLastRest(new ClientCompressionFilter(restRequestContentEncoding, getRestRequestCompressionConfig(httpServiceName, restRequestContentEncoding), buildRestAcceptEncodingSchemaNames(responseEncodings), _responseCompressionConfigs.get(httpServiceName), httpResponseCompressionOperations));
        }
        if (streamRequestContentEncoding != StreamEncodingType.IDENTITY || !httpResponseCompressionOperations.isEmpty()) {
            CompressionConfig compressionConfig = getStreamRequestCompressionConfig(httpServiceName, streamRequestContentEncoding);
            filters = filters.addLast(new ClientStreamCompressionFilter(streamRequestContentEncoding, compressionConfig, buildStreamAcceptEncodingSchemas(responseEncodings), _responseCompressionConfigs.get(httpServiceName), httpResponseCompressionOperations, _compressionExecutor));
        }
    }
    Integer queryPostThreshold = chooseNewOverDefault(getIntValue(properties, HTTP_QUERY_POST_THRESHOLD), Integer.MAX_VALUE);
    ClientQueryTunnelFilter clientQueryTunnelFilter = new ClientQueryTunnelFilter(queryPostThreshold);
    filters = filters.addLastRest(clientQueryTunnelFilter);
    filters = filters.addLast(clientQueryTunnelFilter);
    // Add the disruptor filter to the end of the filter chain to get the most accurate simulation of disrupt
    Integer requestTimeout = chooseNewOverDefault(getIntValue(properties, HTTP_REQUEST_TIMEOUT), DEFAULT_REQUEST_TIMEOUT);
    DisruptFilter disruptFilter = new DisruptFilter(_executor, _eventLoopGroup, requestTimeout);
    filters = filters.addLastRest(disruptFilter);
    filters = filters.addLast(disruptFilter);
    client = new FilterChainClient(client, filters);
    client = new FactoryClient(client);
    synchronized (_mutex) {
        if (!_running) {
            throw new IllegalStateException("Factory is shutting down");
        }
        _clientsOutstanding++;
        return client;
    }
}
Also used : TransportClient(com.linkedin.r2.transport.common.bridge.client.TransportClient) FilterChain(com.linkedin.r2.filter.FilterChain) StreamEncodingType(com.linkedin.r2.filter.compression.streaming.StreamEncodingType) EncodingType(com.linkedin.r2.filter.compression.EncodingType) DisruptFilter(com.linkedin.r2.disruptor.DisruptFilter) StreamEncodingType(com.linkedin.r2.filter.compression.streaming.StreamEncodingType) ClientStreamCompressionFilter(com.linkedin.r2.filter.compression.ClientStreamCompressionFilter) FilterChainClient(com.linkedin.r2.filter.transport.FilterChainClient) ClientQueryTunnelFilter(com.linkedin.r2.filter.transport.ClientQueryTunnelFilter) ClientCompressionFilter(com.linkedin.r2.filter.compression.ClientCompressionFilter) CompressionConfig(com.linkedin.r2.filter.CompressionConfig)

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