Search in sources :

Example 6 with HystrixContextRunnable

use of com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable in project Hystrix by Netflix.

the class RollingThreadPoolMaxConcurrencyStreamTest method testConcurrencyStreamProperlyFiltersOutSemaphoreRejections.

@Test
public void testConcurrencyStreamProperlyFiltersOutSemaphoreRejections() throws InterruptedException {
    HystrixCommandGroupKey groupKey = HystrixCommandGroupKey.Factory.asKey("ThreadPool-Concurrency-I");
    HystrixThreadPoolKey threadPoolKey = HystrixThreadPoolKey.Factory.asKey("ThreadPool-Concurrency-I");
    HystrixCommandKey key = HystrixCommandKey.Factory.asKey("RollingConcurrency-I");
    stream = RollingThreadPoolMaxConcurrencyStream.getInstance(threadPoolKey, 10, 100);
    stream.startCachingStreamValuesIfUnstarted();
    final CountDownLatch latch = new CountDownLatch(1);
    stream.observe().take(10).subscribe(getSubscriber(latch));
    //10 commands executed concurrently on different caller threads should saturate semaphore
    //once these are in-flight, execute 10 more concurrently on new caller threads.
    //since these are semaphore-rejected, the max concurrency should be 10
    List<Command> saturators = new ArrayList<Command>();
    for (int i = 0; i < 10; i++) {
        saturators.add(Command.from(groupKey, key, HystrixEventType.SUCCESS, 400, HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE));
    }
    final List<Command> rejected = new ArrayList<Command>();
    for (int i = 0; i < 10; i++) {
        rejected.add(Command.from(groupKey, key, HystrixEventType.SUCCESS, 100, HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE));
    }
    for (final Command saturatingCmd : saturators) {
        threadPool.submit(new HystrixContextRunnable(new Runnable() {

            @Override
            public void run() {
                saturatingCmd.observe();
            }
        }));
    }
    Thread.sleep(30);
    for (final Command rejectedCmd : rejected) {
        threadPool.submit(new HystrixContextRunnable(new Runnable() {

            @Override
            public void run() {
                rejectedCmd.observe();
            }
        }));
    }
    assertTrue(latch.await(10000, TimeUnit.MILLISECONDS));
    System.out.println("ReqLog : " + HystrixRequestLog.getCurrentRequest().getExecutedCommandsAsString());
    for (Command rejectedCmd : rejected) {
        assertTrue(rejectedCmd.isResponseSemaphoreRejected() || rejectedCmd.isResponseShortCircuited());
    }
    //should be 0 since all are executed in a semaphore
    assertEquals(0, stream.getLatestRollingMax());
}
Also used : HystrixCommandKey(com.netflix.hystrix.HystrixCommandKey) HystrixContextRunnable(com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable) HystrixContextRunnable(com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable) ArrayList(java.util.ArrayList) HystrixThreadPoolKey(com.netflix.hystrix.HystrixThreadPoolKey) CountDownLatch(java.util.concurrent.CountDownLatch) HystrixCommandGroupKey(com.netflix.hystrix.HystrixCommandGroupKey) CommandStreamTest(com.netflix.hystrix.metric.CommandStreamTest) Test(org.junit.Test)

Example 7 with HystrixContextRunnable

use of com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable in project Hystrix by Netflix.

the class HystrixCollapserTest method testRequestVariableLifecycle2.

@Test
public void testRequestVariableLifecycle2() throws Exception {
    final HystrixRequestContext reqContext = HystrixRequestContext.initializeContext();
    final TestCollapserTimer timer = new TestCollapserTimer();
    final ConcurrentLinkedQueue<Future<String>> responses = new ConcurrentLinkedQueue<Future<String>>();
    ConcurrentLinkedQueue<Thread> threads = new ConcurrentLinkedQueue<Thread>();
    // kick off work (simulating a single request with multiple threads)
    for (int t = 0; t < 5; t++) {
        final int outerLoop = t;
        Thread th = new Thread(new HystrixContextRunnable(HystrixPlugins.getInstance().getConcurrencyStrategy(), new Runnable() {

            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    int uniqueInt = (outerLoop * 100) + i;
                    responses.add(new TestRequestCollapser(timer, uniqueInt).queue());
                }
            }
        }));
        threads.add(th);
        th.start();
    }
    for (Thread th : threads) {
        // wait for each thread to finish
        th.join();
    }
    // we expect 5 threads * 100 responses each
    assertEquals(500, responses.size());
    for (Future<String> f : responses) {
        // they should not be done yet because the counter hasn't incremented
        assertFalse(f.isDone());
    }
    timer.incrementTime(5);
    HystrixCollapser<List<String>, String, String> collapser1 = new TestRequestCollapser(timer, 2);
    Future<String> response2 = collapser1.queue();
    timer.incrementTime(8);
    // should execute here
    Future<String> response3 = new TestRequestCollapser(timer, 3).queue();
    timer.incrementTime(6);
    Future<String> response4 = new TestRequestCollapser(timer, 4).queue();
    timer.incrementTime(8);
    // should execute here
    Future<String> response5 = new TestRequestCollapser(timer, 5).queue();
    timer.incrementTime(10);
    // wait for all tasks to complete
    for (Future<String> f : responses) {
        f.get(1000, TimeUnit.MILLISECONDS);
    }
    assertEquals("2", response2.get(1000, TimeUnit.MILLISECONDS));
    assertEquals("3", response3.get(1000, TimeUnit.MILLISECONDS));
    assertEquals("4", response4.get(1000, TimeUnit.MILLISECONDS));
    assertEquals("5", response5.get(1000, TimeUnit.MILLISECONDS));
    // each task should have been executed 3 times
    for (TestCollapserTimer.ATask t : timer.tasks) {
        assertEquals(3, t.task.count.get());
    }
    Iterator<HystrixInvokableInfo<?>> cmdIterator = HystrixRequestLog.getCurrentRequest().getAllExecutedCommands().iterator();
    assertEquals(500, cmdIterator.next().getNumberCollapsed());
    assertEquals(2, cmdIterator.next().getNumberCollapsed());
    assertEquals(1, cmdIterator.next().getNumberCollapsed());
    HystrixRequestVariableHolder<RequestCollapser<?, ?, ?>> rv = RequestCollapserFactory.getRequestVariable(new TestRequestCollapser(timer, 1).getCollapserKey().name());
    reqContext.close();
    assertNotNull(rv);
    // they should have all been removed as part of ThreadContext.remove()
    assertEquals(0, timer.tasks.size());
}
Also used : HystrixContextRunnable(com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable) HystrixContextRunnable(com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable) Future(java.util.concurrent.Future) RequestCollapser(com.netflix.hystrix.collapser.RequestCollapser) HystrixRequestContext(com.netflix.hystrix.strategy.concurrency.HystrixRequestContext) ArrayList(java.util.ArrayList) List(java.util.List) ConcurrentLinkedQueue(java.util.concurrent.ConcurrentLinkedQueue) Test(org.junit.Test)

Example 8 with HystrixContextRunnable

use of com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable in project Hystrix by Netflix.

the class HystrixCommandTest method testRejectedExecutionSemaphoreWithFallbackViaExecute.

@Test
public void testRejectedExecutionSemaphoreWithFallbackViaExecute() throws Exception {
    final TestCircuitBreaker circuitBreaker = new TestCircuitBreaker();
    final ArrayBlockingQueue<Boolean> results = new ArrayBlockingQueue<Boolean>(2);
    final AtomicBoolean exceptionReceived = new AtomicBoolean();
    final TestSemaphoreCommandWithFallback command1 = new TestSemaphoreCommandWithFallback(circuitBreaker, 1, 200, false);
    Runnable r1 = new HystrixContextRunnable(HystrixPlugins.getInstance().getConcurrencyStrategy(), new Runnable() {

        @Override
        public void run() {
            try {
                results.add(command1.execute());
            } catch (Exception e) {
                e.printStackTrace();
                exceptionReceived.set(true);
            }
        }
    });
    final TestSemaphoreCommandWithFallback command2 = new TestSemaphoreCommandWithFallback(circuitBreaker, 1, 200, false);
    Runnable r2 = new HystrixContextRunnable(HystrixPlugins.getInstance().getConcurrencyStrategy(), new Runnable() {

        @Override
        public void run() {
            try {
                results.add(command2.execute());
            } catch (Exception e) {
                e.printStackTrace();
                exceptionReceived.set(true);
            }
        }
    });
    // 2 threads, the second should be rejected by the semaphore and return fallback
    Thread t1 = new Thread(r1);
    Thread t2 = new Thread(r2);
    t1.start();
    // make sure that t2 gets a chance to run before queuing the next one
    Thread.sleep(50);
    t2.start();
    t1.join();
    t2.join();
    if (exceptionReceived.get()) {
        fail("We should have received a fallback response");
    }
    // both threads should have returned values
    assertEquals(2, results.size());
    // should contain both a true and false result
    assertTrue(results.contains(Boolean.TRUE));
    assertTrue(results.contains(Boolean.FALSE));
    assertCommandExecutionEvents(command1, HystrixEventType.SUCCESS);
    assertCommandExecutionEvents(command2, HystrixEventType.SEMAPHORE_REJECTED, HystrixEventType.FALLBACK_SUCCESS);
    assertEquals(0, circuitBreaker.metrics.getCurrentConcurrentExecutionCount());
    assertSaneHystrixRequestLog(2);
}
Also used : AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) TestCircuitBreaker(com.netflix.hystrix.HystrixCircuitBreakerTest.TestCircuitBreaker) ArrayBlockingQueue(java.util.concurrent.ArrayBlockingQueue) HystrixContextRunnable(com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable) HystrixContextRunnable(com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) TimeoutException(java.util.concurrent.TimeoutException) HystrixRuntimeException(com.netflix.hystrix.exception.HystrixRuntimeException) RejectedExecutionException(java.util.concurrent.RejectedExecutionException) HystrixBadRequestException(com.netflix.hystrix.exception.HystrixBadRequestException) CancellationException(java.util.concurrent.CancellationException) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) Test(org.junit.Test)

Example 9 with HystrixContextRunnable

use of com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable in project Hystrix by Netflix.

the class HystrixCommandTest method testExecutionSemaphoreWithQueue.

@Test
public void testExecutionSemaphoreWithQueue() throws Exception {
    final TestCircuitBreaker circuitBreaker = new TestCircuitBreaker();
    // single thread should work
    TestSemaphoreCommand command1 = new TestSemaphoreCommand(circuitBreaker, 1, 200, TestSemaphoreCommand.RESULT_SUCCESS, TestSemaphoreCommand.FALLBACK_NOT_IMPLEMENTED);
    boolean result = command1.queue().get();
    assertTrue(result);
    final AtomicBoolean exceptionReceived = new AtomicBoolean();
    final TryableSemaphore semaphore = new TryableSemaphoreActual(HystrixProperty.Factory.asProperty(1));
    final TestSemaphoreCommand command2 = new TestSemaphoreCommand(circuitBreaker, semaphore, 200, TestSemaphoreCommand.RESULT_SUCCESS, TestSemaphoreCommand.FALLBACK_NOT_IMPLEMENTED);
    Runnable r2 = new HystrixContextRunnable(HystrixPlugins.getInstance().getConcurrencyStrategy(), new Runnable() {

        @Override
        public void run() {
            try {
                command2.queue().get();
            } catch (Exception e) {
                e.printStackTrace();
                exceptionReceived.set(true);
            }
        }
    });
    final TestSemaphoreCommand command3 = new TestSemaphoreCommand(circuitBreaker, semaphore, 200, TestSemaphoreCommand.RESULT_SUCCESS, TestSemaphoreCommand.FALLBACK_NOT_IMPLEMENTED);
    Runnable r3 = new HystrixContextRunnable(HystrixPlugins.getInstance().getConcurrencyStrategy(), new Runnable() {

        @Override
        public void run() {
            try {
                command3.queue().get();
            } catch (Exception e) {
                e.printStackTrace();
                exceptionReceived.set(true);
            }
        }
    });
    // 2 threads, the second should be rejected by the semaphore
    Thread t2 = new Thread(r2);
    Thread t3 = new Thread(r3);
    t2.start();
    // make sure that t2 gets a chance to run before queuing the next one
    Thread.sleep(50);
    t3.start();
    t2.join();
    t3.join();
    if (!exceptionReceived.get()) {
        fail("We expected an exception on the 2nd get");
    }
    assertCommandExecutionEvents(command1, HystrixEventType.SUCCESS);
    assertCommandExecutionEvents(command2, HystrixEventType.SUCCESS);
    assertCommandExecutionEvents(command3, HystrixEventType.SEMAPHORE_REJECTED, HystrixEventType.FALLBACK_MISSING);
    assertEquals(0, circuitBreaker.metrics.getCurrentConcurrentExecutionCount());
    assertSaneHystrixRequestLog(3);
}
Also used : AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) TestCircuitBreaker(com.netflix.hystrix.HystrixCircuitBreakerTest.TestCircuitBreaker) HystrixContextRunnable(com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable) TryableSemaphoreActual(com.netflix.hystrix.AbstractCommand.TryableSemaphoreActual) HystrixContextRunnable(com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable) TryableSemaphore(com.netflix.hystrix.AbstractCommand.TryableSemaphore) TimeoutException(java.util.concurrent.TimeoutException) HystrixRuntimeException(com.netflix.hystrix.exception.HystrixRuntimeException) RejectedExecutionException(java.util.concurrent.RejectedExecutionException) HystrixBadRequestException(com.netflix.hystrix.exception.HystrixBadRequestException) CancellationException(java.util.concurrent.CancellationException) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) Test(org.junit.Test)

Example 10 with HystrixContextRunnable

use of com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable in project Hystrix by Netflix.

the class HystrixCommandTest method testSemaphorePermitsInUse.

/**
     * Tests that semaphores are counted separately for commands with unique keys
     */
@Test
public void testSemaphorePermitsInUse() throws Exception {
    final TestCircuitBreaker circuitBreaker = new TestCircuitBreaker();
    // this semaphore will be shared across multiple command instances
    final TryableSemaphoreActual sharedSemaphore = new TryableSemaphoreActual(HystrixProperty.Factory.asProperty(3));
    // used to wait until all commands have started
    final CountDownLatch startLatch = new CountDownLatch((sharedSemaphore.numberOfPermits.get() * 2) + 1);
    // used to signal that all command can finish
    final CountDownLatch sharedLatch = new CountDownLatch(1);
    // tracks failures to obtain semaphores
    final AtomicInteger failureCount = new AtomicInteger();
    final Runnable sharedSemaphoreRunnable = new HystrixContextRunnable(HystrixPlugins.getInstance().getConcurrencyStrategy(), new Runnable() {

        public void run() {
            try {
                new LatchedSemaphoreCommand("Command-Shared", circuitBreaker, sharedSemaphore, startLatch, sharedLatch).execute();
            } catch (Exception e) {
                startLatch.countDown();
                e.printStackTrace();
                failureCount.incrementAndGet();
            }
        }
    });
    // creates group of threads each using command sharing a single semaphore
    // I create extra threads and commands so that I can verify that some of them fail to obtain a semaphore
    final int sharedThreadCount = sharedSemaphore.numberOfPermits.get() * 2;
    final Thread[] sharedSemaphoreThreads = new Thread[sharedThreadCount];
    for (int i = 0; i < sharedThreadCount; i++) {
        sharedSemaphoreThreads[i] = new Thread(sharedSemaphoreRunnable);
    }
    // creates thread using isolated semaphore
    final TryableSemaphoreActual isolatedSemaphore = new TryableSemaphoreActual(HystrixProperty.Factory.asProperty(1));
    final CountDownLatch isolatedLatch = new CountDownLatch(1);
    final Thread isolatedThread = new Thread(new HystrixContextRunnable(HystrixPlugins.getInstance().getConcurrencyStrategy(), new Runnable() {

        public void run() {
            try {
                new LatchedSemaphoreCommand("Command-Isolated", circuitBreaker, isolatedSemaphore, startLatch, isolatedLatch).execute();
            } catch (Exception e) {
                startLatch.countDown();
                e.printStackTrace();
                failureCount.incrementAndGet();
            }
        }
    }));
    // verifies no permits in use before starting threads
    assertEquals("before threads start, shared semaphore should be unused", 0, sharedSemaphore.getNumberOfPermitsUsed());
    assertEquals("before threads start, isolated semaphore should be unused", 0, isolatedSemaphore.getNumberOfPermitsUsed());
    for (int i = 0; i < sharedThreadCount; i++) {
        sharedSemaphoreThreads[i].start();
    }
    isolatedThread.start();
    // waits until all commands have started
    startLatch.await(1000, TimeUnit.MILLISECONDS);
    // verifies that all semaphores are in use
    assertEquals("immediately after command start, all shared semaphores should be in-use", sharedSemaphore.numberOfPermits.get().longValue(), sharedSemaphore.getNumberOfPermitsUsed());
    assertEquals("immediately after command start, isolated semaphore should be in-use", isolatedSemaphore.numberOfPermits.get().longValue(), isolatedSemaphore.getNumberOfPermitsUsed());
    // signals commands to finish
    sharedLatch.countDown();
    isolatedLatch.countDown();
    for (int i = 0; i < sharedThreadCount; i++) {
        sharedSemaphoreThreads[i].join();
    }
    isolatedThread.join();
    // verifies no permits in use after finishing threads
    System.out.println("REQLOG : " + HystrixRequestLog.getCurrentRequest().getExecutedCommandsAsString());
    assertEquals("after all threads have finished, no shared semaphores should be in-use", 0, sharedSemaphore.getNumberOfPermitsUsed());
    assertEquals("after all threads have finished, isolated semaphore not in-use", 0, isolatedSemaphore.getNumberOfPermitsUsed());
    // verifies that some executions failed
    assertEquals("expected some of shared semaphore commands to get rejected", sharedSemaphore.numberOfPermits.get().longValue(), failureCount.get());
    assertEquals(0, circuitBreaker.metrics.getCurrentConcurrentExecutionCount());
}
Also used : TestCircuitBreaker(com.netflix.hystrix.HystrixCircuitBreakerTest.TestCircuitBreaker) HystrixContextRunnable(com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable) TryableSemaphoreActual(com.netflix.hystrix.AbstractCommand.TryableSemaphoreActual) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) HystrixContextRunnable(com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable) CountDownLatch(java.util.concurrent.CountDownLatch) TimeoutException(java.util.concurrent.TimeoutException) HystrixRuntimeException(com.netflix.hystrix.exception.HystrixRuntimeException) RejectedExecutionException(java.util.concurrent.RejectedExecutionException) HystrixBadRequestException(com.netflix.hystrix.exception.HystrixBadRequestException) CancellationException(java.util.concurrent.CancellationException) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) Test(org.junit.Test)

Aggregations

HystrixContextRunnable (com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable)18 Test (org.junit.Test)18 CountDownLatch (java.util.concurrent.CountDownLatch)11 ArrayList (java.util.ArrayList)10 TestCircuitBreaker (com.netflix.hystrix.HystrixCircuitBreakerTest.TestCircuitBreaker)8 HystrixCommandKey (com.netflix.hystrix.HystrixCommandKey)8 HystrixBadRequestException (com.netflix.hystrix.exception.HystrixBadRequestException)8 HystrixRuntimeException (com.netflix.hystrix.exception.HystrixRuntimeException)8 CommandStreamTest (com.netflix.hystrix.metric.CommandStreamTest)8 IOException (java.io.IOException)8 ExecutionException (java.util.concurrent.ExecutionException)8 TimeoutException (java.util.concurrent.TimeoutException)8 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)7 ArrayBlockingQueue (java.util.concurrent.ArrayBlockingQueue)5 CancellationException (java.util.concurrent.CancellationException)5 RejectedExecutionException (java.util.concurrent.RejectedExecutionException)5 TryableSemaphoreActual (com.netflix.hystrix.AbstractCommand.TryableSemaphoreActual)4 HystrixCommandGroupKey (com.netflix.hystrix.HystrixCommandGroupKey)3 HystrixThreadPoolKey (com.netflix.hystrix.HystrixThreadPoolKey)3 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)3