Search in sources :

Example 11 with HystrixContextRunnable

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

the class HystrixObservableCommandTest method testRejectedExecutionSemaphoreWithFallback.

@Test
public void testRejectedExecutionSemaphoreWithFallback() {
    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.observe().toBlocking().single());
            } 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.observe().toBlocking().single());
            } 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();
    try {
        //give t1 a headstart
        Thread.sleep(50);
    } catch (InterruptedException ex) {
        fail(ex.getMessage());
    }
    t2.start();
    try {
        t1.join();
        t2.join();
    } catch (Exception e) {
        e.printStackTrace();
        fail("failed waiting on threads");
    }
    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.EMIT, HystrixEventType.SUCCESS);
    assertCommandExecutionEvents(command2, HystrixEventType.SEMAPHORE_REJECTED, HystrixEventType.FALLBACK_EMIT, HystrixEventType.FALLBACK_SUCCESS);
    assertEquals(0, command1.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) HystrixBadRequestException(com.netflix.hystrix.exception.HystrixBadRequestException) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) Test(org.junit.Test)

Example 12 with HystrixContextRunnable

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

the class HealthCountsStreamTest method testSemaphoreRejected.

@Test
public void testSemaphoreRejected() {
    HystrixCommandKey key = HystrixCommandKey.Factory.asKey("CMD-Health-H");
    stream = HealthCountsStream.getInstance(key, 10, 100);
    final CountDownLatch latch = new CountDownLatch(1);
    stream.observe().take(10).subscribe(getSubscriber(latch));
    //10 commands will saturate semaphore when called from different threads.
    //submit 2 more requests and they should be SEMAPHORE_REJECTED
    //should see 10 SUCCESSes, 2 SEMAPHORE_REJECTED and 2 FALLBACK_SUCCESSes
    List<Command> saturators = new ArrayList<Command>();
    for (int i = 0; i < 10; i++) {
        saturators.add(CommandStreamTest.Command.from(groupKey, key, HystrixEventType.SUCCESS, 400, HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE));
    }
    CommandStreamTest.Command rejected1 = CommandStreamTest.Command.from(groupKey, key, HystrixEventType.SUCCESS, 0, HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE);
    CommandStreamTest.Command rejected2 = CommandStreamTest.Command.from(groupKey, key, HystrixEventType.SUCCESS, 0, HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE);
    for (final CommandStreamTest.Command saturator : saturators) {
        new Thread(new HystrixContextRunnable(new Runnable() {

            @Override
            public void run() {
                saturator.observe();
            }
        })).start();
    }
    try {
        Thread.sleep(100);
    } catch (InterruptedException ie) {
        fail(ie.getMessage());
    }
    rejected1.observe();
    rejected2.observe();
    try {
        assertTrue(latch.await(10000, TimeUnit.MILLISECONDS));
    } catch (InterruptedException ex) {
        fail("Interrupted ex");
    }
    System.out.println("ReqLog : " + HystrixRequestLog.getCurrentRequest().getExecutedCommandsAsString());
    assertTrue(rejected1.isResponseSemaphoreRejected());
    assertTrue(rejected2.isResponseSemaphoreRejected());
    assertEquals(2L, stream.getLatest().getErrorCount());
    assertEquals(12L, stream.getLatest().getTotalRequests());
}
Also used : HystrixCommandKey(com.netflix.hystrix.HystrixCommandKey) CommandStreamTest(com.netflix.hystrix.metric.CommandStreamTest) ArrayList(java.util.ArrayList) CountDownLatch(java.util.concurrent.CountDownLatch) HystrixContextRunnable(com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable) HystrixCommand(com.netflix.hystrix.HystrixCommand) HystrixContextRunnable(com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable) CommandStreamTest(com.netflix.hystrix.metric.CommandStreamTest) Test(org.junit.Test)

Example 13 with HystrixContextRunnable

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

the class HystrixObservableCommandTest method testRejectedViaThreadIsolation.

@Test
public void testRejectedViaThreadIsolation() throws InterruptedException {
    final TestCircuitBreaker circuitBreaker = new TestCircuitBreaker();
    final ArrayBlockingQueue<Boolean> results = new ArrayBlockingQueue<Boolean>(10);
    final List<Thread> executionThreads = Collections.synchronizedList(new ArrayList<Thread>(20));
    final List<Thread> responseThreads = Collections.synchronizedList(new ArrayList<Thread>(10));
    final AtomicBoolean exceptionReceived = new AtomicBoolean();
    final CountDownLatch scheduleLatch = new CountDownLatch(2);
    final CountDownLatch successLatch = new CountDownLatch(1);
    final AtomicInteger count = new AtomicInteger();
    final AtomicReference<TestThreadIsolationWithSemaphoreSetSmallCommand> command1Ref = new AtomicReference<TestThreadIsolationWithSemaphoreSetSmallCommand>();
    final AtomicReference<TestThreadIsolationWithSemaphoreSetSmallCommand> command2Ref = new AtomicReference<TestThreadIsolationWithSemaphoreSetSmallCommand>();
    final AtomicReference<TestThreadIsolationWithSemaphoreSetSmallCommand> command3Ref = new AtomicReference<TestThreadIsolationWithSemaphoreSetSmallCommand>();
    Runnable r1 = new HystrixContextRunnable(HystrixPlugins.getInstance().getConcurrencyStrategy(), new Runnable() {

        @Override
        public void run() {
            final boolean shouldExecute = count.incrementAndGet() < 3;
            try {
                executionThreads.add(Thread.currentThread());
                TestThreadIsolationWithSemaphoreSetSmallCommand command1 = new TestThreadIsolationWithSemaphoreSetSmallCommand(circuitBreaker, 2, new Action0() {

                    @Override
                    public void call() {
                        // make sure it's deterministic and we put 2 threads into the pool before the 3rd is submitted
                        if (shouldExecute) {
                            try {
                                scheduleLatch.countDown();
                                successLatch.await();
                            } catch (InterruptedException e) {
                            }
                        }
                    }
                });
                command1Ref.set(command1);
                results.add(command1.toObservable().map(new Func1<Boolean, Boolean>() {

                    @Override
                    public Boolean call(Boolean b) {
                        responseThreads.add(Thread.currentThread());
                        return b;
                    }
                }).doAfterTerminate(new Action0() {

                    @Override
                    public void call() {
                        if (!shouldExecute) {
                            // the final thread that shouldn't execute releases the latch once it has run
                            // so it is deterministic that the other two fill the thread pool until this one rejects
                            successLatch.countDown();
                        }
                    }
                }).toBlocking().single());
            } catch (Exception e) {
                e.printStackTrace();
                exceptionReceived.set(true);
            }
        }
    });
    Runnable r2 = new HystrixContextRunnable(HystrixPlugins.getInstance().getConcurrencyStrategy(), new Runnable() {

        @Override
        public void run() {
            final boolean shouldExecute = count.incrementAndGet() < 3;
            try {
                executionThreads.add(Thread.currentThread());
                TestThreadIsolationWithSemaphoreSetSmallCommand command2 = new TestThreadIsolationWithSemaphoreSetSmallCommand(circuitBreaker, 2, new Action0() {

                    @Override
                    public void call() {
                        // make sure it's deterministic and we put 2 threads into the pool before the 3rd is submitted
                        if (shouldExecute) {
                            try {
                                scheduleLatch.countDown();
                                successLatch.await();
                            } catch (InterruptedException e) {
                            }
                        }
                    }
                });
                command2Ref.set(command2);
                results.add(command2.toObservable().map(new Func1<Boolean, Boolean>() {

                    @Override
                    public Boolean call(Boolean b) {
                        responseThreads.add(Thread.currentThread());
                        return b;
                    }
                }).doAfterTerminate(new Action0() {

                    @Override
                    public void call() {
                        if (!shouldExecute) {
                            // the final thread that shouldn't execute releases the latch once it has run
                            // so it is deterministic that the other two fill the thread pool until this one rejects
                            successLatch.countDown();
                        }
                    }
                }).toBlocking().single());
            } catch (Exception e) {
                e.printStackTrace();
                exceptionReceived.set(true);
            }
        }
    });
    Runnable r3 = new HystrixContextRunnable(HystrixPlugins.getInstance().getConcurrencyStrategy(), new Runnable() {

        @Override
        public void run() {
            final boolean shouldExecute = count.incrementAndGet() < 3;
            try {
                executionThreads.add(Thread.currentThread());
                TestThreadIsolationWithSemaphoreSetSmallCommand command3 = new TestThreadIsolationWithSemaphoreSetSmallCommand(circuitBreaker, 2, new Action0() {

                    @Override
                    public void call() {
                        // make sure it's deterministic and we put 2 threads into the pool before the 3rd is submitted
                        if (shouldExecute) {
                            try {
                                scheduleLatch.countDown();
                                successLatch.await();
                            } catch (InterruptedException e) {
                            }
                        }
                    }
                });
                command3Ref.set(command3);
                results.add(command3.toObservable().map(new Func1<Boolean, Boolean>() {

                    @Override
                    public Boolean call(Boolean b) {
                        responseThreads.add(Thread.currentThread());
                        return b;
                    }
                }).doAfterTerminate(new Action0() {

                    @Override
                    public void call() {
                        if (!shouldExecute) {
                            // the final thread that shouldn't execute releases the latch once it has run
                            // so it is deterministic that the other two fill the thread pool until this one rejects
                            successLatch.countDown();
                        }
                    }
                }).toBlocking().single());
            } 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);
    Thread t3 = new Thread(r3);
    t1.start();
    t2.start();
    // wait for the previous 2 thread to be running before starting otherwise it can race
    scheduleLatch.await(500, TimeUnit.MILLISECONDS);
    t3.start();
    try {
        t1.join();
        t2.join();
        t3.join();
    } catch (Exception e) {
        e.printStackTrace();
        fail("failed waiting on threads");
    }
    // we should have 2 of the 3 return results
    assertEquals(2, results.size());
    // the other thread should have thrown an Exception
    assertTrue(exceptionReceived.get());
    assertCommandExecutionEvents(command1Ref.get(), HystrixEventType.EMIT, HystrixEventType.SUCCESS);
    assertCommandExecutionEvents(command2Ref.get(), HystrixEventType.EMIT, HystrixEventType.SUCCESS);
    assertCommandExecutionEvents(command3Ref.get(), HystrixEventType.THREAD_POOL_REJECTED, HystrixEventType.FALLBACK_MISSING);
    assertEquals(0, circuitBreaker.metrics.getCurrentConcurrentExecutionCount());
    assertSaneHystrixRequestLog(3);
}
Also used : TestCircuitBreaker(com.netflix.hystrix.HystrixCircuitBreakerTest.TestCircuitBreaker) Action0(rx.functions.Action0) AtomicReference(java.util.concurrent.atomic.AtomicReference) CountDownLatch(java.util.concurrent.CountDownLatch) TimeoutException(java.util.concurrent.TimeoutException) HystrixRuntimeException(com.netflix.hystrix.exception.HystrixRuntimeException) HystrixBadRequestException(com.netflix.hystrix.exception.HystrixBadRequestException) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) ArrayBlockingQueue(java.util.concurrent.ArrayBlockingQueue) HystrixContextRunnable(com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) HystrixContextRunnable(com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Func1(rx.functions.Func1) Test(org.junit.Test)

Example 14 with HystrixContextRunnable

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

the class HystrixObservableCollapserTest method testCollapserUnderConcurrency.

@Test
public void testCollapserUnderConcurrency() throws InterruptedException {
    final CollapserTimer timer = new RealCollapserTimer();
    final int NUM_THREADS_SUBMITTING_WORK = 8;
    final int NUM_REQUESTS_PER_THREAD = 8;
    final CountDownLatch latch = new CountDownLatch(NUM_THREADS_SUBMITTING_WORK);
    List<Runnable> runnables = new ArrayList<Runnable>();
    final ConcurrentLinkedQueue<TestSubscriber<String>> subscribers = new ConcurrentLinkedQueue<TestSubscriber<String>>();
    HystrixRequestContext context = HystrixRequestContext.initializeContext();
    final AtomicInteger uniqueInt = new AtomicInteger(0);
    for (int i = 0; i < NUM_THREADS_SUBMITTING_WORK; i++) {
        runnables.add(new Runnable() {

            @Override
            public void run() {
                try {
                    for (int j = 0; j < NUM_REQUESTS_PER_THREAD; j++) {
                        HystrixObservableCollapser<String, String, String, String> collapser = new TestCollapserWithMultipleResponses(timer, uniqueInt.getAndIncrement(), 3, false);
                        Observable<String> o = collapser.toObservable();
                        TestSubscriber<String> subscriber = new TestSubscriber<String>();
                        o.subscribe(subscriber);
                        subscribers.offer(subscriber);
                    }
                //System.out.println("Runnable done on thread : " + Thread.currentThread().getName());
                } finally {
                    latch.countDown();
                }
            }
        });
    }
    for (Runnable r : runnables) {
        threadPool.submit(new HystrixContextRunnable(r));
    }
    assertTrue(latch.await(1000, TimeUnit.MILLISECONDS));
    for (TestSubscriber<String> subscriber : subscribers) {
        subscriber.awaitTerminalEvent();
        if (subscriber.getOnErrorEvents().size() > 0) {
            System.out.println("ERROR : " + subscriber.getOnErrorEvents());
            for (Throwable ex : subscriber.getOnErrorEvents()) {
                ex.printStackTrace();
            }
        }
        subscriber.assertCompleted();
        subscriber.assertNoErrors();
        System.out.println("Received : " + subscriber.getOnNextEvents());
        subscriber.assertValueCount(3);
    }
    context.shutdown();
}
Also used : RealCollapserTimer(com.netflix.hystrix.collapser.RealCollapserTimer) CollapserTimer(com.netflix.hystrix.collapser.CollapserTimer) TestCollapserTimer(com.netflix.hystrix.HystrixCollapserTest.TestCollapserTimer) RealCollapserTimer(com.netflix.hystrix.collapser.RealCollapserTimer) ArrayList(java.util.ArrayList) CountDownLatch(java.util.concurrent.CountDownLatch) Observable(rx.Observable) HystrixContextRunnable(com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) HystrixContextRunnable(com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable) TestSubscriber(rx.observers.TestSubscriber) HystrixRequestContext(com.netflix.hystrix.strategy.concurrency.HystrixRequestContext) ConcurrentLinkedQueue(java.util.concurrent.ConcurrentLinkedQueue) Test(org.junit.Test)

Example 15 with HystrixContextRunnable

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

the class HystrixObservableCommandTest method testExecutionSemaphoreWithObserve.

@Test
public void testExecutionSemaphoreWithObserve() {
    final TestCircuitBreaker circuitBreaker = new TestCircuitBreaker();
    TestSemaphoreCommand command1 = new TestSemaphoreCommand(circuitBreaker, 1, 200, TestSemaphoreCommand.RESULT_SUCCESS, TestSemaphoreCommand.FALLBACK_NOT_IMPLEMENTED);
    // single thread should work
    try {
        boolean result = command1.observe().toBlocking().toFuture().get();
        assertTrue(result);
    } catch (Exception e) {
        // we shouldn't fail on this one
        throw new RuntimeException(e);
    }
    final AtomicBoolean exceptionReceived = new AtomicBoolean();
    final TryableSemaphoreActual 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.observe().toBlocking().toFuture().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.observe().toBlocking().toFuture().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();
    try {
        Thread.sleep(100);
    } catch (Throwable ex) {
        fail(ex.getMessage());
    }
    t3.start();
    try {
        t2.join();
        t3.join();
    } catch (Exception e) {
        e.printStackTrace();
        fail("failed waiting on threads");
    }
    if (!exceptionReceived.get()) {
        fail("We expected an exception on the 2nd get");
    }
    System.out.println("CMD1 : " + command1.getExecutionEvents());
    System.out.println("CMD2 : " + command2.getExecutionEvents());
    System.out.println("CMD3 : " + command3.getExecutionEvents());
    assertCommandExecutionEvents(command1, HystrixEventType.EMIT, HystrixEventType.SUCCESS);
    assertCommandExecutionEvents(command2, HystrixEventType.EMIT, 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) HystrixRuntimeException(com.netflix.hystrix.exception.HystrixRuntimeException) HystrixContextRunnable(com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable) TryableSemaphoreActual(com.netflix.hystrix.AbstractCommand.TryableSemaphoreActual) HystrixContextRunnable(com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable) TimeoutException(java.util.concurrent.TimeoutException) HystrixRuntimeException(com.netflix.hystrix.exception.HystrixRuntimeException) HystrixBadRequestException(com.netflix.hystrix.exception.HystrixBadRequestException) 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