@Test(expected = HystrixBadRequestException.class) public void testGetUserByNameIgnoreBadRequestException() { restClient.getUserByNameIgnoreExc(" "); assertEquals(1, HystrixRequestLog.getCurrentRequest().getExecutedCommands().size()); HystrixCommand getUserByNameIgnoreExc = getHystrixCommandByKey("getUserByNameIgnoreExc"); assertTrue(getUserByNameIgnoreExc.getExecutionEvents().contains(HystrixEventType.FAILURE)); }
@Test public void testFindAllAsynchronouslyWithFallback() throws ExecutionException, InterruptedException { int commandCount = 1; int fallbackCount = 2; List<User> users = restClient.findAllAsync(3, 10).get(); assertEquals(1, users.size()); assertEquals(DEF_USER, users.get(0)); assertEquals( commandCount + fallbackCount, HystrixRequestLog.getCurrentRequest().getExecutedCommands().size()); HystrixCommand findAllAsyncCommand = getHystrixCommandByKey("findAllAsync"); HystrixCommand findAllFallbackCommand = getHystrixCommandByKey("findAllFallback"); HystrixCommand findAllFallback2Command = getHystrixCommandByKey("findAllFallback2"); assertTrue(findAllAsyncCommand.isFailedExecution()); assertTrue(findAllFallbackCommand.isFailedExecution()); assertTrue(findAllFallback2Command.isExecutionComplete()); assertExecutedCommands("findAllAsync", "findAllFallback", "findAllFallback2"); // confirm that initial command has failed assertTrue(findAllAsyncCommand.getExecutionEvents().contains(HystrixEventType.FAILURE)); // confirm that fallback has failed assertTrue(findAllFallbackCommand.getExecutionEvents().contains(HystrixEventType.FAILURE)); // and that last fallback was successful assertTrue( findAllFallbackCommand.getExecutionEvents().contains(HystrixEventType.FALLBACK_SUCCESS)); }
public static void main(String... args) { // initialize DiscoveryAndLoadBalancer.getFactory(); // hystrix stream => http://localhost:9999 startHystrixMetricsStream(); System.out.println("Server => Starting at http://localhost:8080/"); System.out.println(" Sample URLs: "); System.out.println(" - http://localhost:8080/device/home?userId=123"); System.out.println("----------------------------------------------------------------"); // start web services => http://localhost:8080 RxNetty.createHttpServer( 8080, (request, response) -> { if (request.getPath().contains("favicon.ico")) { return Observable.empty(); } // System.out.println("Server => Request: " + request.getPath()); return Observable.defer( () -> { HystrixRequestContext.initializeContext(); try { return handleRoutes(request, response); } catch (Throwable e) { System.err.println("Server => Error [" + request.getPath() + "] => " + e); response.setStatus(HttpResponseStatus.BAD_REQUEST); return response.writeStringAndFlush( "Error 500: Bad Request\n" + e.getMessage() + "\n"); } }) .onErrorResumeNext( error -> { System.err.println("Server => Error: " + error.getMessage()); error.printStackTrace(); return writeError(request, response, "Failed: " + error.getMessage()); }) .doOnTerminate( () -> { if (HystrixRequestContext.isCurrentThreadInitialized()) { System.out.println( "Server => Request [" + request.getPath() + "] => " + HystrixRequestLog.getCurrentRequest() .getExecutedCommandsAsString()); HystrixRequestContext.getContextForCurrentThread().shutdown(); } else { System.err.println( "HystrixRequestContext not initialized for thread: " + Thread.currentThread()); } response.close(); }); }) .startAndWait(); }
/** * Test that an open circuit is closed after 1 success. This also ensures that the rolling window * (containing failures) is cleared after the sleep window Otherwise, the next bucket roll would * produce another signal to fail unless it is explicitly cleared (via {@link * HystrixCommandMetrics#resetStream()}. */ @Test public void testCircuitClosedAfterSuccess() { String key = "cmd-G"; try { int sleepWindow = 20; HystrixCommand<Boolean> cmd1 = new FailureCommand(key, 1, sleepWindow); HystrixCircuitBreaker cb = cmd1.circuitBreaker; // this should start as allowing requests assertTrue(cb.allowRequest()); assertFalse(cb.isOpen()); cmd1.execute(); HystrixCommand<Boolean> cmd2 = new FailureCommand(key, 1, sleepWindow); cmd2.execute(); HystrixCommand<Boolean> cmd3 = new FailureCommand(key, 1, sleepWindow); cmd3.execute(); HystrixCommand<Boolean> cmd4 = new TimeoutCommand(key, sleepWindow); cmd4.execute(); // everything has failed in the test window so we should return false now Thread.sleep(100); System.out.println( "ReqLog : " + HystrixRequestLog.getCurrentRequest().getExecutedCommandsAsString()); System.out.println("CircuitBreaker state 1 : " + cmd1.getMetrics().getHealthCounts()); assertFalse(cb.allowRequest()); assertTrue(cb.isOpen()); // wait for sleepWindow to pass Thread.sleep(sleepWindow + 50); // but the circuit should still be open assertTrue(cb.isOpen()); // we should now allow 1 request, and upon success, should cause the circuit to be closed HystrixCommand<Boolean> cmd5 = new SuccessCommand(key, 60, sleepWindow); Observable<Boolean> asyncResult = cmd5.observe(); // and further requests are still blocked while the singleTest command is in flight assertFalse(cb.allowRequest()); asyncResult.toBlocking().single(); // all requests should be open again System.out.println("CircuitBreaker state 2 : " + cmd1.getMetrics().getHealthCounts()); assertTrue(cb.allowRequest()); assertTrue(cb.allowRequest()); assertTrue(cb.allowRequest()); // and the circuit should be closed again assertFalse(cb.isOpen()); } catch (Exception e) { e.printStackTrace(); fail("Error occurred: " + e.getMessage()); } }
@Test public void testCollapser() throws ExecutionException, InterruptedException { User u1 = userService.getUser("1"); User u2 = userService.getUser("2"); User u3 = userService.getUser("3"); User u4 = userService.getUser("4"); assertEquals("name: 1", u1.getName()); assertEquals("name: 2", u2.getName()); assertEquals("name: 3", u3.getName()); assertEquals("name: 4", u4.getName()); assertEquals(4, HystrixRequestLog.getCurrentRequest().getAllExecutedCommands().size()); HystrixInvokableInfo<?> command = HystrixRequestLog.getCurrentRequest().getAllExecutedCommands().iterator().next(); assertEquals("getUsers", command.getCommandKey().name()); // confirm that it was a COLLAPSED command execution assertTrue(command.getExecutionEvents().contains(HystrixEventType.COLLAPSED)); // and that it was successful assertTrue(command.getExecutionEvents().contains(HystrixEventType.SUCCESS)); }
@Test public void testGetUserByIdSuccess() { User user = restClient.getUserById("1"); User exUser = new User("1", "Alex"); assertExecutedCommands("GetUserByIdCommand"); assertEquals(1, HystrixRequestLog.getCurrentRequest().getExecutedCommands().size()); HystrixCommand getUserByIdCommand = getHystrixCommandByKey("GetUserByIdCommand"); assertEquals("SimpleRestClient", getUserByIdCommand.getCommandGroup().name()); assertEquals("GetUserByIdCommand", getUserByIdCommand.getCommandKey().name()); assertEquals(exUser, user); // confirm that command has success assertTrue(getUserByIdCommand.getExecutionEvents().contains(HystrixEventType.SUCCESS)); }
@Test public void testGetUserByName() { User user = restClient.getUserByName("timeout"); assertExecutedCommands("GetUserByNameCommand"); assertEquals(DEF_USER, user); assertEquals(1, HystrixRequestLog.getCurrentRequest().getExecutedCommands().size()); HystrixCommand<?> hystrixCommand = HystrixRequestLog.getCurrentRequest() .getExecutedCommands() .toArray(new HystrixCommand<?>[1])[0]; assertEquals("GetUserByNameCommand", hystrixCommand.getCommandKey().name()); assertEquals("SimpleRestClientTest", hystrixCommand.getThreadPoolKey().name()); assertFalse(hystrixCommand.isExecutedInThread()); assertEquals( Integer.valueOf(500), hystrixCommand.getProperties().executionIsolationThreadTimeoutInMilliseconds().get()); // confirm that command has failed assertTrue(hystrixCommand.getExecutionEvents().contains(HystrixEventType.FAILURE)); // and that fallback was successful assertTrue(hystrixCommand.getExecutionEvents().contains(HystrixEventType.FALLBACK_SUCCESS)); }
/** Test that if the % of failures is higher than the threshold that the circuit trips. */ @Test public void testCircuitDoesNotTripOnFailuresBelowThreshold() { String key = "cmd-C"; try { HystrixCommand<Boolean> cmd1 = new SuccessCommand(key, 60); HystrixCircuitBreaker cb = cmd1.circuitBreaker; // this should start as allowing requests assertTrue(cb.allowRequest()); assertFalse(cb.isOpen()); // success with high latency cmd1.execute(); HystrixCommand<Boolean> cmd2 = new SuccessCommand(key, 1); cmd2.execute(); HystrixCommand<Boolean> cmd3 = new FailureCommand(key, 1); cmd3.execute(); HystrixCommand<Boolean> cmd4 = new SuccessCommand(key, 1); cmd4.execute(); HystrixCommand<Boolean> cmd5 = new SuccessCommand(key, 1); cmd5.execute(); HystrixCommand<Boolean> cmd6 = new FailureCommand(key, 1); cmd6.execute(); HystrixCommand<Boolean> cmd7 = new SuccessCommand(key, 1); cmd7.execute(); HystrixCommand<Boolean> cmd8 = new FailureCommand(key, 1); cmd8.execute(); // this should remain closed as the failure threshold is below the percentage limit Thread.sleep(100); System.out.println( "ReqLog : " + HystrixRequestLog.getCurrentRequest().getExecutedCommandsAsString()); System.out.println("Current CircuitBreaker Status : " + cmd1.getMetrics().getHealthCounts()); assertTrue(cb.allowRequest()); assertFalse(cb.isOpen()); } catch (Exception e) { e.printStackTrace(); fail("Error occurred: " + e.getMessage()); } }
protected void assertSaneHystrixRequestLog(final int numCommands) { HystrixRequestLog currentRequestLog = HystrixRequestLog.getCurrentRequest(); try { assertEquals(numCommands, currentRequestLog.getAllExecutedCommands().size()); assertFalse(currentRequestLog.getExecutedCommandsAsString().contains("Executed")); assertTrue( currentRequestLog.getAllExecutedCommands().iterator().next().getExecutionEvents().size() >= 1); // Most commands should have 1 execution event, but fallbacks / responses from cache can cause // more than 1. They should never have 0 } catch (Throwable ex) { System.out.println( "Problematic Request log : " + currentRequestLog.getExecutedCommandsAsString() + " , expected : " + numCommands); throw new RuntimeException(ex); } }
public void shutdown(HystrixRequestLog value) { // write this value to the Request stream HystrixRequestEventsStream.getInstance().write(value.getAllExecutedCommands()); }