Search in sources :

Example 1 with TryableSemaphoreActual

use of com.netflix.hystrix.AbstractCommand.TryableSemaphoreActual in project Hystrix by Netflix.

the class HystrixCommandTest method testExecutionSemaphoreWithExecution.

@Test
public void testExecutionSemaphoreWithExecution() 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.execute();
    assertFalse(command1.isExecutedInThread());
    assertTrue(result);
    final ArrayBlockingQueue<Boolean> results = new ArrayBlockingQueue<Boolean>(2);
    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 {
                results.add(command2.execute());
            } 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 {
                results.add(command3.execute());
            } 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");
    }
    // only 1 value is expected as the other should have thrown an exception
    assertEquals(1, results.size());
    // should contain only a true result
    assertTrue(results.contains(Boolean.TRUE));
    assertFalse(results.contains(Boolean.FALSE));
    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 : TestCircuitBreaker(com.netflix.hystrix.HystrixCircuitBreakerTest.TestCircuitBreaker) TryableSemaphoreActual(com.netflix.hystrix.AbstractCommand.TryableSemaphoreActual) 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) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) 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) TryableSemaphore(com.netflix.hystrix.AbstractCommand.TryableSemaphore) Test(org.junit.Test)

Example 2 with TryableSemaphoreActual

use of com.netflix.hystrix.AbstractCommand.TryableSemaphoreActual in project Hystrix by Netflix.

the class HystrixObservableCommandTest method testSemaphorePermitsInUse.

@Test
public void testSemaphorePermitsInUse() {
    // this semaphore will be shared across multiple command instances
    final TryableSemaphoreActual sharedSemaphore = new TryableSemaphoreActual(HystrixProperty.Factory.asProperty(3));
    // creates thread using isolated semaphore
    final TryableSemaphoreActual isolatedSemaphore = new TryableSemaphoreActual(HystrixProperty.Factory.asProperty(1));
    final TestCircuitBreaker circuitBreaker = new TestCircuitBreaker();
    // used to wait until all commands are 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);
    final CountDownLatch isolatedLatch = new CountDownLatch(1);
    final List<HystrixObservableCommand<Boolean>> commands = new ArrayList<HystrixObservableCommand<Boolean>>();
    final List<Observable<Boolean>> results = new ArrayList<Observable<Boolean>>();
    HystrixObservableCommand<Boolean> isolated = new LatchedSemaphoreCommand("ObservableCommand-Isolated", circuitBreaker, isolatedSemaphore, startLatch, isolatedLatch);
    commands.add(isolated);
    for (int s = 0; s < sharedSemaphore.numberOfPermits.get() * 2; s++) {
        HystrixObservableCommand<Boolean> shared = new LatchedSemaphoreCommand("ObservableCommand-Shared", circuitBreaker, sharedSemaphore, startLatch, sharedLatch);
        commands.add(shared);
        Observable<Boolean> result = shared.toObservable();
        results.add(result);
    }
    Observable<Boolean> isolatedResult = isolated.toObservable();
    results.add(isolatedResult);
    // verifies no permits in use before starting commands
    assertEquals("before commands start, shared semaphore should be unused", 0, sharedSemaphore.getNumberOfPermitsUsed());
    assertEquals("before commands start, isolated semaphore should be unused", 0, isolatedSemaphore.getNumberOfPermitsUsed());
    final CountDownLatch allTerminal = new CountDownLatch(1);
    Observable.merge(results).subscribeOn(Schedulers.newThread()).subscribe(new Subscriber<Boolean>() {

        @Override
        public void onCompleted() {
            System.out.println(Thread.currentThread().getName() + " OnCompleted");
            allTerminal.countDown();
        }

        @Override
        public void onError(Throwable e) {
            System.out.println(Thread.currentThread().getName() + " OnError : " + e);
            allTerminal.countDown();
        }

        @Override
        public void onNext(Boolean b) {
            System.out.println(Thread.currentThread().getName() + " OnNext : " + b);
        }
    });
    try {
        assertTrue(startLatch.await(20, TimeUnit.SECONDS));
    } catch (Throwable ex) {
        fail(ex.getMessage());
    }
    // 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();
    try {
        assertTrue(allTerminal.await(5000, TimeUnit.MILLISECONDS));
    } catch (Exception e) {
        e.printStackTrace();
        fail("failed waiting on commands");
    }
    // verifies no permits in use after finishing threads
    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
    int numSemaphoreRejected = 0;
    for (HystrixObservableCommand<Boolean> cmd : commands) {
        if (cmd.isResponseSemaphoreRejected()) {
            numSemaphoreRejected++;
        }
    }
    assertEquals("expected some of shared semaphore commands to get rejected", sharedSemaphore.numberOfPermits.get().longValue(), numSemaphoreRejected);
}
Also used : TestCircuitBreaker(com.netflix.hystrix.HystrixCircuitBreakerTest.TestCircuitBreaker) TryableSemaphoreActual(com.netflix.hystrix.AbstractCommand.TryableSemaphoreActual) ArrayList(java.util.ArrayList) 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) Test(org.junit.Test)

Example 3 with TryableSemaphoreActual

use of com.netflix.hystrix.AbstractCommand.TryableSemaphoreActual 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)

Example 4 with TryableSemaphoreActual

use of com.netflix.hystrix.AbstractCommand.TryableSemaphoreActual 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 5 with TryableSemaphoreActual

use of com.netflix.hystrix.AbstractCommand.TryableSemaphoreActual 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

TryableSemaphoreActual (com.netflix.hystrix.AbstractCommand.TryableSemaphoreActual)7 Test (org.junit.Test)7 TestCircuitBreaker (com.netflix.hystrix.HystrixCircuitBreakerTest.TestCircuitBreaker)6 HystrixBadRequestException (com.netflix.hystrix.exception.HystrixBadRequestException)5 HystrixRuntimeException (com.netflix.hystrix.exception.HystrixRuntimeException)5 HystrixContextRunnable (com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable)5 IOException (java.io.IOException)5 ExecutionException (java.util.concurrent.ExecutionException)5 TimeoutException (java.util.concurrent.TimeoutException)5 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)5 CountDownLatch (java.util.concurrent.CountDownLatch)4 CancellationException (java.util.concurrent.CancellationException)3 RejectedExecutionException (java.util.concurrent.RejectedExecutionException)3 TryableSemaphore (com.netflix.hystrix.AbstractCommand.TryableSemaphore)2 ArrayBlockingQueue (java.util.concurrent.ArrayBlockingQueue)2 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)2 ArrayList (java.util.ArrayList)1 ExecutorService (java.util.concurrent.ExecutorService)1