Search in sources :

Example 81 with Timeout

use of com.linkedin.r2.util.Timeout in project rest.li by linkedin.

the class WarmUpLoadBalancerTest method testNotDeletingFilesGetClient.

/**
 * Since the list might from the fetcher might not be complete (update service, old data, etc.., and the user might
 * require additional services at runtime, we have to check that those services are not cleared from the cache
 * otherwise it would incur in a penalty at the next deployment
 */
@Test(timeOut = 10000)
public void testNotDeletingFilesGetClient() throws InterruptedException, ExecutionException, TimeoutException, ServiceUnavailableException {
    createDefaultServicesIniFiles();
    TestLoadBalancer balancer = new TestLoadBalancer();
    List<String> allServicesBeforeShutdown = getAllDownstreamServices();
    DownstreamServicesFetcher returnNoDownstreams = callback -> callback.onSuccess(Collections.emptyList());
    String pickOneService = allServicesBeforeShutdown.get(0);
    LoadBalancer warmUpLoadBalancer = new WarmUpLoadBalancer(balancer, balancer, Executors.newSingleThreadScheduledExecutor(), _tmpdir.getAbsolutePath(), MY_SERVICES_FS, returnNoDownstreams, WarmUpLoadBalancer.DEFAULT_SEND_REQUESTS_TIMEOUT_SECONDS, WarmUpLoadBalancer.DEFAULT_CONCURRENT_REQUESTS);
    FutureCallback<None> callback = new FutureCallback<>();
    warmUpLoadBalancer.start(callback);
    callback.get(5000, TimeUnit.MILLISECONDS);
    warmUpLoadBalancer.getClient(new URIRequest("d2://" + pickOneService), new RequestContext());
    FutureCallback<None> shutdownCallback = new FutureCallback<>();
    warmUpLoadBalancer.shutdown(() -> shutdownCallback.onSuccess(None.none()));
    shutdownCallback.get(5000, TimeUnit.MILLISECONDS);
    List<String> allServicesAfterShutdown = getAllDownstreamServices();
    Assert.assertEquals(1, allServicesAfterShutdown.size(), "After shutdown there should be just one service, the one that we 'get the client' on");
}
Also used : Arrays(java.util.Arrays) FutureCallback(com.linkedin.common.callback.FutureCallback) DownstreamServicesFetcher(com.linkedin.d2.balancer.util.downstreams.DownstreamServicesFetcher) URISyntaxException(java.net.URISyntaxException) BeforeMethod(org.testng.annotations.BeforeMethod) TimeoutException(java.util.concurrent.TimeoutException) IOException(java.io.IOException) Test(org.testng.annotations.Test) AfterMethod(org.testng.annotations.AfterMethod) FSBasedDownstreamServicesFetcher(com.linkedin.d2.balancer.util.downstreams.FSBasedDownstreamServicesFetcher) File(java.io.File) Executors(java.util.concurrent.Executors) ArrayList(java.util.ArrayList) ExecutionException(java.util.concurrent.ExecutionException) TimeUnit(java.util.concurrent.TimeUnit) List(java.util.List) RequestContext(com.linkedin.r2.message.RequestContext) Assert(org.testng.Assert) None(com.linkedin.common.util.None) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) LoadBalancer(com.linkedin.d2.balancer.LoadBalancer) ServiceUnavailableException(com.linkedin.d2.balancer.ServiceUnavailableException) Collections(java.util.Collections) DownstreamServicesFetcher(com.linkedin.d2.balancer.util.downstreams.DownstreamServicesFetcher) FSBasedDownstreamServicesFetcher(com.linkedin.d2.balancer.util.downstreams.FSBasedDownstreamServicesFetcher) LoadBalancer(com.linkedin.d2.balancer.LoadBalancer) RequestContext(com.linkedin.r2.message.RequestContext) None(com.linkedin.common.util.None) FutureCallback(com.linkedin.common.callback.FutureCallback) Test(org.testng.annotations.Test)

Example 82 with Timeout

use of com.linkedin.r2.util.Timeout in project rest.li by linkedin.

the class SimpleLoadBalancerSimulation method verifyState.

/**
 * Compare the simulator's view of reality with the load balancer's. This method should
 * be called after every step is performed and all threads have finished.
 */
public void verifyState() {
    // verify that we consumed all messages before we do anything
    for (int i = 0; i < _queues.length; ++i) {
        if (_queues[i].size() > 0) {
            fail("there were messages left in the queue. all messages should have been consumed during this simulation step.");
        }
    }
    // verify that all clients have been shut down
    for (Map.Entry<String, TransportClientFactory> e : _clientFactories.entrySet()) {
        DoNothingClientFactory factory = (DoNothingClientFactory) e.getValue();
        if (factory.getRunningClientCount() != 0) {
            fail("Not all clients were shut down from factory " + e.getKey());
        }
    }
    try {
        final CountDownLatch latch = new CountDownLatch(1);
        PropertyEventShutdownCallback callback = new PropertyEventShutdownCallback() {

            @Override
            public void done() {
                latch.countDown();
            }
        };
        _state.shutdown(callback);
        if (!latch.await(60, TimeUnit.SECONDS)) {
            fail("unable to shutdown state");
        }
    } catch (InterruptedException e) {
        fail("unable to shutdown state in verifyState.");
    }
    // New load balancer with no timeout; the code below checks for services that don't
    // exist,
    // and a load balancer with non-zero timeout will just timeout waiting for them to be
    // registered, which will never happen because the PropertyEventThread is shut down.
    _loadBalancer = new SimpleLoadBalancer(_state, 0, TimeUnit.SECONDS, _executorService);
    // verify services are as we expect
    for (String possibleService : _possibleServices) {
        // about it
        if (!_expectedServiceProperties.containsKey(possibleService) || !_state.isListeningToService(possibleService)) {
            LoadBalancerStateItem<ServiceProperties> serviceItem = _state.getServiceProperties(possibleService);
            assertTrue(serviceItem == null || serviceItem.getProperty() == null);
        } else {
            ServiceProperties serviceProperties = _expectedServiceProperties.get(possibleService);
            ClusterProperties clusterProperties = _expectedClusterProperties.get(serviceProperties.getClusterName());
            UriProperties uriProperties = _expectedUriProperties.get(serviceProperties.getClusterName());
            assertEquals(_state.getServiceProperties(possibleService).getProperty(), serviceProperties);
            // verify round robin'ing of the hosts for this service
            for (int i = 0; i < 100; ++i) {
                try {
                    // this call will queue up messages if we're not listening to the service, but
                    // it's ok, because all of the messengers have been stopped.
                    final TransportClient client = _loadBalancer.getClient(new URIRequest("d2://" + possibleService + random(_possiblePaths)), new RequestContext());
                    // if we didn't receive service unavailable, we should
                    // get a client back
                    assertNotNull(client, "Not found client for: d2://" + possibleService + random(_possiblePaths));
                } catch (ServiceUnavailableException e) {
                    if (uriProperties != null && clusterProperties != null) {
                        // only way to get here is if the prioritized
                        // schemes could find no available uris in the
                        // cluster. let's see if we can find a URI that
                        // matches a prioritized scheme in the cluster.
                        Set<String> schemes = new HashSet<>();
                        for (URI uri : uriProperties.Uris()) {
                            schemes.add(uri.getScheme());
                        }
                        for (String scheme : clusterProperties.getPrioritizedSchemes()) {
                            // the code.
                            if (schemes.contains(scheme) && _clientFactories.containsKey(scheme)) {
                                break;
                            }
                            assertFalse(schemes.contains(scheme) && _clientFactories.containsKey(scheme), "why couldn't a client be found for schemes " + clusterProperties.getPrioritizedSchemes() + " with URIs: " + uriProperties.Uris());
                        }
                    }
                }
            }
        }
    }
    // verify clusters are as we expect
    for (String possibleCluster : _possibleClusters) {
        LoadBalancerStateItem<ClusterProperties> clusterItem = _state.getClusterProperties(possibleCluster);
        if (!_expectedClusterProperties.containsKey(possibleCluster) || !_state.isListeningToCluster(possibleCluster)) {
            assertTrue(clusterItem == null || clusterItem.getProperty() == null, "cluster item for " + possibleCluster + " is not null: " + clusterItem);
        } else {
            assertNotNull(clusterItem, "Item for cluster " + possibleCluster + " should not be null, listening: " + _state.isListeningToCluster(possibleCluster) + ", keys: " + _expectedClusterProperties.keySet());
            assertEquals(clusterItem.getProperty(), _expectedClusterProperties.get(possibleCluster));
        }
    }
    // verify uris are as we expect
    for (String possibleCluster : _possibleClusters) {
        LoadBalancerStateItem<UriProperties> uriItem = _state.getUriProperties(possibleCluster);
        if (!_expectedUriProperties.containsKey(possibleCluster) || !_state.isListeningToCluster(possibleCluster)) {
            assertTrue(uriItem == null || uriItem.getProperty() == null);
        } else {
            assertNotNull(uriItem);
            assertEquals(uriItem.getProperty(), _expectedUriProperties.get(possibleCluster));
        }
    }
}
Also used : PropertyEventShutdownCallback(com.linkedin.d2.discovery.event.PropertyEventThread.PropertyEventShutdownCallback) TransportClient(com.linkedin.r2.transport.common.bridge.client.TransportClient) Set(java.util.Set) HashSet(java.util.HashSet) SimpleLoadBalancer(com.linkedin.d2.balancer.simple.SimpleLoadBalancer) URIRequest(com.linkedin.d2.balancer.util.URIRequest) ServiceUnavailableException(com.linkedin.d2.balancer.ServiceUnavailableException) CountDownLatch(java.util.concurrent.CountDownLatch) URI(java.net.URI) DoNothingClientFactory(com.linkedin.d2.balancer.simple.SimpleLoadBalancerTest.DoNothingClientFactory) ServiceProperties(com.linkedin.d2.balancer.properties.ServiceProperties) UriProperties(com.linkedin.d2.balancer.properties.UriProperties) ClusterProperties(com.linkedin.d2.balancer.properties.ClusterProperties) RequestContext(com.linkedin.r2.message.RequestContext) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) TransportClientFactory(com.linkedin.r2.transport.common.TransportClientFactory)

Example 83 with Timeout

use of com.linkedin.r2.util.Timeout in project rest.li by linkedin.

the class TestRestLiMethodInvocation method testTimeoutParseqTracePromise.

@Test(dataProvider = "promiseMethodConfigProviders")
public void testTimeoutParseqTracePromise(RestLiMethodConfig restliMethodConfig, String timeoutTaskName) throws Exception {
    Map<String, ResourceModel> resourceModelMap = buildResourceModels(PromiseStatusCollectionResource.class);
    ResourceModel promiseStatusResourceModel = resourceModelMap.get("/promisestatuses");
    // Promise based Async Method Execution
    RequestContext promiseRequestContext = new RequestContext();
    ResourceMethodDescriptor methodDescriptor = promiseStatusResourceModel.findMethod(ResourceMethod.GET);
    PromiseStatusCollectionResource promiseStatusResource = getMockResource(PromiseStatusCollectionResource.class);
    EasyMock.expect(promiseStatusResource.get(eq(1L))).andReturn(Promises.value(new Status())).once();
    // configure method-level timeout
    ResourceMethodConfigProvider methodConfigProvider = ResourceMethodConfigProvider.build(restliMethodConfig);
    ResourceMethodConfig methodConfig = methodConfigProvider.apply(methodDescriptor);
    checkInvocation(promiseStatusResource, promiseRequestContext, methodDescriptor, methodConfig, "GET", version, "/promisestatuses/1", null, buildPathKeys("statusID", 1L), new Callback<RestResponse>() {

        @Override
        public void onError(Throwable e) {
            Assert.fail("Request failed unexpectedly.");
        }

        @Override
        public void onSuccess(RestResponse result) {
            Trace parseqTrace = (Trace) promiseRequestContext.getLocalAttr(ATTRIBUTE_PARSEQ_TRACE);
            Assert.assertNotNull(parseqTrace);
            if (timeoutTaskName != null) {
                Assert.assertTrue(hasTask(timeoutTaskName, parseqTrace));
            }
        }
    }, true, false, null, null);
}
Also used : Status(com.linkedin.restli.server.twitter.TwitterTestDataModels.Status) HttpStatus(com.linkedin.restli.common.HttpStatus) PromiseStatusCollectionResource(com.linkedin.restli.server.twitter.PromiseStatusCollectionResource) RestResponse(com.linkedin.r2.message.rest.RestResponse) ResourceMethodDescriptor(com.linkedin.restli.internal.server.model.ResourceMethodDescriptor) ByteString(com.linkedin.data.ByteString) CustomString(com.linkedin.restli.server.custom.types.CustomString) ResourceMethodConfigProvider(com.linkedin.restli.server.config.ResourceMethodConfigProvider) Trace(com.linkedin.parseq.trace.Trace) ResourceModel(com.linkedin.restli.internal.server.model.ResourceModel) RestLiTestHelper.buildResourceModel(com.linkedin.restli.server.test.RestLiTestHelper.buildResourceModel) ResourceMethodConfig(com.linkedin.restli.server.config.ResourceMethodConfig) FilterRequestContext(com.linkedin.restli.server.filter.FilterRequestContext) RequestContext(com.linkedin.r2.message.RequestContext) Test(org.testng.annotations.Test) AfterTest(org.testng.annotations.AfterTest) BeforeTest(org.testng.annotations.BeforeTest)

Example 84 with Timeout

use of com.linkedin.r2.util.Timeout in project rest.li by linkedin.

the class AbstractAsyncR2StreamServlet method service.

@Override
public void service(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
    final AsyncContext ctx = req.startAsync(req, resp);
    ctx.setTimeout(_timeout);
    final WrappedAsyncContext wrappedCtx = new WrappedAsyncContext(ctx);
    final AsyncEventIOHandler ioHandler = new AsyncEventIOHandler(req.getInputStream(), resp.getOutputStream(), req.getRemoteAddr(), wrappedCtx, MAX_BUFFERED_CHUNKS, _logServletExceptions);
    final RequestContext requestContext = ServletHelper.readRequestContext(req);
    final StreamRequest streamRequest;
    try {
        streamRequest = ServletHelper.readFromServletRequest(req, ioHandler);
    } catch (URISyntaxException e) {
        ServletHelper.writeToServletError(resp, RestStatus.BAD_REQUEST, e.toString());
        wrappedCtx.complete();
        return;
    }
    final AtomicBoolean startedResponding = new AtomicBoolean(false);
    ctx.addListener(new AsyncListener() {

        @Override
        public void onTimeout(AsyncEvent event) throws IOException {
            LOG.error("Server timeout for request: " + formatURI(req.getRequestURI()));
            if (startedResponding.compareAndSet(false, true)) {
                LOG.info("Returning server timeout response");
                ServletHelper.writeToServletError(resp, RestStatus.INTERNAL_SERVER_ERROR, "Server timeout");
            } else {
                req.setAttribute(ASYNC_IOEXCEPTION, new ServletException("Server timeout"));
            }
            ioHandler.exitLoop();
            wrappedCtx.complete();
        }

        @Override
        public void onStartAsync(AsyncEvent event) throws IOException {
        // Nothing to do here
        }

        @Override
        public void onError(AsyncEvent event) throws IOException {
            LOG.error("Server error for request: " + formatURI(req.getRequestURI()));
            if (startedResponding.compareAndSet(false, true)) {
                LOG.info("Returning server error response");
                ServletHelper.writeToServletError(resp, RestStatus.INTERNAL_SERVER_ERROR, "Server error");
            } else {
                req.setAttribute(ASYNC_IOEXCEPTION, new ServletException("Server error"));
            }
            ioHandler.exitLoop();
            wrappedCtx.complete();
        }

        @Override
        public void onComplete(AsyncEvent event) throws IOException {
            Object exception = req.getAttribute(ASYNC_IOEXCEPTION);
            if (exception != null) {
                throw new IOException((Throwable) exception);
            }
        }
    });
    final TransportCallback<StreamResponse> callback = new TransportCallback<StreamResponse>() {

        @Override
        public void onResponse(final TransportResponse<StreamResponse> response) {
            if (startedResponding.compareAndSet(false, true)) {
                ctx.start(new Runnable() {

                    @Override
                    public void run() {
                        try {
                            StreamResponse streamResponse = ServletHelper.writeResponseHeadersToServletResponse(response, resp);
                            streamResponse.getEntityStream().setReader(ioHandler);
                            ioHandler.loop();
                        } catch (Exception e) {
                            req.setAttribute(ASYNC_IOEXCEPTION, e);
                            wrappedCtx.complete();
                        }
                    }
                });
            } else {
                LOG.error("Dropped a response; this is mostly like because that AsyncContext timeout or error had already happened");
            }
        }
    };
    // we have to use a new thread and let this thread return to pool. otherwise the timeout won't start
    ctx.start(new Runnable() {

        @Override
        public void run() {
            try {
                getDispatcher().handleRequest(streamRequest, requestContext, callback);
                ioHandler.loop();
            } catch (Exception e) {
                req.setAttribute(ASYNC_IOEXCEPTION, e);
                wrappedCtx.complete();
            }
        }
    });
}
Also used : TransportCallback(com.linkedin.r2.transport.common.bridge.common.TransportCallback) StreamResponse(com.linkedin.r2.message.stream.StreamResponse) AsyncContext(javax.servlet.AsyncContext) URISyntaxException(java.net.URISyntaxException) IOException(java.io.IOException) AsyncEvent(javax.servlet.AsyncEvent) TransportResponse(com.linkedin.r2.transport.common.bridge.common.TransportResponse) ServletException(javax.servlet.ServletException) URISyntaxException(java.net.URISyntaxException) IOException(java.io.IOException) StreamRequest(com.linkedin.r2.message.stream.StreamRequest) ServletException(javax.servlet.ServletException) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) AsyncListener(javax.servlet.AsyncListener) RequestContext(com.linkedin.r2.message.RequestContext)

Example 85 with Timeout

use of com.linkedin.r2.util.Timeout in project rest.li by linkedin.

the class TestStreamClientTimeout method testReadAfterTimeout.

@Test
public void testReadAfterTimeout() throws Exception {
    StreamRequest request = new StreamRequestBuilder(_clientProvider.createHttpURI(_port, NORMAL_URI)).build(EntityStreams.emptyStream());
    final CountDownLatch latch = new CountDownLatch(1);
    final AtomicReference<StreamResponse> response = new AtomicReference<>();
    _client.streamRequest(request, new Callback<StreamResponse>() {

        @Override
        public void onError(Throwable e) {
            latch.countDown();
        }

        @Override
        public void onSuccess(StreamResponse result) {
            response.set(result);
            latch.countDown();
        }
    });
    latch.await(5000, TimeUnit.MILLISECONDS);
    Assert.assertNotNull(response.get());
    // let it timeout before we read
    Thread.sleep(5000);
    final AtomicReference<Throwable> throwable = new AtomicReference<>();
    final CountDownLatch errorLatch = new CountDownLatch(1);
    Reader reader = new DrainReader() {

        @Override
        public void onError(Throwable ex) {
            throwable.set(ex);
            errorLatch.countDown();
        }
    };
    response.get().getEntityStream().setReader(reader);
    errorLatch.await(5000, TimeUnit.MILLISECONDS);
    Assert.assertNotNull(throwable.get());
    Throwable rootCause = ExceptionUtils.getRootCause(throwable.get());
    Assert.assertTrue(rootCause instanceof TimeoutException);
}
Also used : StreamResponse(com.linkedin.r2.message.stream.StreamResponse) Reader(com.linkedin.r2.message.stream.entitystream.Reader) DrainReader(com.linkedin.r2.message.stream.entitystream.DrainReader) AtomicReference(java.util.concurrent.atomic.AtomicReference) CountDownLatch(java.util.concurrent.CountDownLatch) StreamRequestBuilder(com.linkedin.r2.message.stream.StreamRequestBuilder) DrainReader(com.linkedin.r2.message.stream.entitystream.DrainReader) StreamRequest(com.linkedin.r2.message.stream.StreamRequest) TimeoutException(java.util.concurrent.TimeoutException) Test(org.testng.annotations.Test) AbstractServiceTest(test.r2.integ.clientserver.providers.AbstractServiceTest)

Aggregations

Test (org.testng.annotations.Test)78 RequestContext (com.linkedin.r2.message.RequestContext)46 CountDownLatch (java.util.concurrent.CountDownLatch)40 TimeoutException (java.util.concurrent.TimeoutException)40 None (com.linkedin.common.util.None)33 FutureCallback (com.linkedin.common.callback.FutureCallback)32 RestRequestBuilder (com.linkedin.r2.message.rest.RestRequestBuilder)26 StreamResponse (com.linkedin.r2.message.stream.StreamResponse)25 URI (java.net.URI)25 RestRequest (com.linkedin.r2.message.rest.RestRequest)21 StreamRequestBuilder (com.linkedin.r2.message.stream.StreamRequestBuilder)21 ByteString (com.linkedin.data.ByteString)19 HashMap (java.util.HashMap)19 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)19 RestResponse (com.linkedin.r2.message.rest.RestResponse)18 StreamRequest (com.linkedin.r2.message.stream.StreamRequest)17 ExecutionException (java.util.concurrent.ExecutionException)17 TransportClient (com.linkedin.r2.transport.common.bridge.client.TransportClient)15 IOException (java.io.IOException)15 TransportCallback (com.linkedin.r2.transport.common.bridge.common.TransportCallback)13