SlideShare a Scribd company logo
1 of 76
Download to read offline
Resilience with Hystrix
An introduction

Uwe Friedrichsen, codecentric AG, 2014
@ufried
Uwe Friedrichsen | uwe.friedrichsen@codecentric.de | http://slideshare.net/ufried | http://ufried.tumblr.com
It‘s all about production!
Production
Availability
Resilience
Fault Tolerance
re•sil•ience (rɪˈzɪl yəns) also re•sil′ien•cy, n.

1.  the power or ability to return to the original form, position,
etc., after being bent, compressed, or stretched; elasticity.
2.  ability to recover readily from illness, depression, adversity,
or the like; buoyancy.

Random House Kernerman Webster's College Dictionary, © 2010 K Dictionaries Ltd.
Copyright 2005, 1997, 1991 by Random House, Inc. All rights reserved.


http://www.thefreedictionary.com/resilience
Implemented patterns






•  Timeout
•  Circuit breaker
•  Load shedder
Supported patterns

•  Bulkheads

(a.k.a. Failure Units)
•  Fail fast
•  Fail silently
•  Graceful degradation of service
•  Failover
•  Escalation
•  Retry
•  ...
That‘s been enough theory
Give us some code – now!
Basics
Hello, world!
public class HelloCommand extends HystrixCommand<String> {
private static final String COMMAND_GROUP = "default";
private final String name;
public HelloCommand(String name) {
super(HystrixCommandGroupKey.Factory.asKey(COMMAND_GROUP));
this.name = name;
}
@Override
protected String run() throws Exception {
return "Hello, " + name;
}
}
@Test
public void shouldGreetWorld() {
String result = new HelloCommand("World").execute();
assertEquals("Hello, World", result);
}
Synchronous execution
@Test
public void shouldExecuteSynchronously() {
String s = new HelloCommand("Bob").execute();
assertEquals("Hello, Bob", s);
}
Asynchronous execution
@Test
public void shouldExecuteAsynchronously() {
Future<String> f = new HelloCommand("Alice").queue();
String s = null;
try {
s = f.get();
} catch (InterruptedException | ExecutionException e) {
// Handle Future.get() exceptions here
}
assertEquals("Hello, Alice", s);
}
Reactive execution (simple)
@Test
public void shouldExecuteReactiveSimple() {
Observable<String> observable =
new HelloCommand("Alice").observe();
String s = observable.toBlockingObservable().single();
assertEquals("Hello, Alice", s);
}
Reactive execution (full)
public class CommandHelloObserver implements Observer<String> {
// Needed for communication between observer and test case
private final AtomicReference<String> aRef;
private final Semaphore semaphore;
public CommandHelloObserver(AtomicReference<String> aRef,
Semaphore semaphore) {
this.aRef = aRef;
this.semaphore = semaphore;
}
@Override
public void onCompleted() { // Not needed here }
@Override
public void onError(Throwable e) { // Not needed here }
@Override
public void onNext(String s) {
aRef.set(s);
semaphore.release();
}
}
@Test
public void shouldExecuteReactiveFull() {
// Needed for communication between observer and test case
AtomicReference<String> aRef = new AtomicReference<>();
Semaphore semaphore = new Semaphore(0);
Observable<String> observable = new HelloCommand("Bob").observe();
Observer<String> observer =
new CommandHelloObserver(aRef, semaphore);
observable.subscribe(observer);
// Wait until observer received a result
try {
semaphore.acquire();
} catch (InterruptedException e) {
// Handle exceptions here
}
String s = aRef.get();
assertEquals("Hello, Bob", s);
}
Fallback
public class FallbackCommand extends HystrixCommand<String> {
private static final String COMMAND_GROUP = "default";
public FallbackCommand() {
super(HystrixCommandGroupKey.Factory.asKey(COMMAND_GROUP));
}
@Override
protected String run() throws Exception {
throw new RuntimeException("I will always fail");
}
@Override
protected String getFallback() {
return "Powered by fallback";
}
}
@Test
public void shouldGetFallbackResponse() {
String s = new FallbackCommand().execute();
assertEquals("Powered by fallback", s);
}
Error propagation
public class ErrorPropagationCommand extends HystrixCommand<String> {
private static final String COMMAND_GROUP = "default";
protected ErrorPropagationCommand() {
super(HystrixCommandGroupKey.Factory.asKey(COMMAND_GROUP));
}
@Override
protected String run() throws Exception {
throw new HystrixBadRequestException("I fail differently",
new RuntimeException("I will always fail"));
}
@Override
protected String getFallback() {
return "Powered by fallback";
}
}
@Test
public void shouldGetFallbackResponse() {
String s = null;
try {
s = new ErrorPropagationCommand().execute();
fail(); // Just to make sure
} catch (HystrixBadRequestException e) {
assertEquals("I will fail differently", e.getMessage());
assertEquals("I will always fail", e.getCause().getMessage());
}
assertNull(s); // Fallback is not triggered
}
How it works
Source: https://github.com/Netflix/Hystrix/wiki/How-it-Works
Source: https://github.com/Netflix/Hystrix/wiki/How-it-Works
Source: https://github.com/Netflix/Hystrix/wiki/How-it-Works
Configuration
Configuration

•  Based on Archaius by Netflix

which extends the Apache Commons Configuration Library
•  Four levels of precedence
1.  Global default from code
2.  Dynamic global default property
3.  Instance default from code
4.  Dynamic instance property

Provides many configuration & tuning options
Configuration – Some examples

•  hystrix.command.*.execution.isolation.strategy

Either “THREAD” or “SEMAPHORE” (Default: THREAD)
•  hystrix.command.*.execution.isolation.thread.timeoutInMilliseconds

Time to wait for the run() method to complete (Default: 1000)
•  h.c.*.execution.isolation.semaphore.maxConcurrentRequests

Maximum number of concurrent requests when using semaphores (Default: 10)
•  hystrix.command.*.circuitBreaker.errorThresholdPercentage

Error percentage at which the breaker trips open (Default: 50)
•  hystrix.command.*.circuitBreaker.sleepWindowInMilliseconds

Time to wait before attempting to reset the breaker after tripping (Default: 5000)
* must be either “default” or the command key name
Configuration – More examples

•  hystrix.threadpool.*.coreSize

Maximum number of concurrent requests when using thread pools (Default: 10)
•  hystrix.threadpool.*.maxQueueSize

Maximum LinkedBlockingQueue size - -1 for using SynchronousQueue (Default: -1)
•  hystrix.threadpool.default.queueSizeRejectionThreshold

Queue size rejection threshold (Default: 5)

… and many more
* must be either “default” or the thread pool key name
Patterns
Timeout
public class LatentResource {
private final long latency;
public LatentResource(long latency) {
this.latency = ((latency < 0L) ? 0L : latency);
}
public String getData() {
addLatency(); // This is the important part
return "Some value”;
}
private void addLatency() {
try {
Thread.sleep(latency);
} catch (InterruptedException e) {
// We do not care about this here
}
}
}
public class TimeoutCommand extends HystrixCommand<String> {
private static final String COMMAND_GROUP = "default";
private final LatentResource resource;
public TimeoutCommand(int timeout, LatentResource resource) {
super(Setter.withGroupKey(
HystrixCommandGroupKey.Factory.asKey(COMMAND_GROUP))
.andCommandPropertiesDefaults(
HystrixCommandProperties.Setter()
.withExecutionIsolationThreadTimeoutInMilliseconds(
timeout)));
this.resource = resource;
}
@Override
protected String run() throws Exception {
return resource.getData();
}
@Override
protected String getFallback() {
return "Resource timed out";
}
}
@Test
public void shouldGetNormalResponse() {
LatentResource resource = new LatentResource(50L);
TimeoutCommand command = new TimeoutCommand(100, resource);
String s = command.execute();
assertEquals("Some value", s);
}
@Test
public void shouldGetFallbackResponse() {
LatentResource resource = new LatentResource(150L);
TimeoutCommand command = new TimeoutCommand(100, resource);
String s = command.execute();
assertEquals("Resource timed out", s);
}
Circuit breaker
public class CircuitBreakerCommand extends HystrixCommand<String> {
private static final String COMMAND_GROUP = "default";
public CircuitBreakerCommand(String name, boolean open) {
super(Setter.withGroupKey(
HystrixCommandGroupKey.Factory.asKey(COMMAND_GROUP))
.andCommandKey(HystrixCommandKey.Factory.asKey(name))
.andCommandPropertiesDefaults(
HystrixCommandProperties.Setter()
.withCircuitBreakerForceOpen(open)));
}
@Override
protected String run() throws Exception {
return("Some result");
}
@Override
protected String getFallback() {
return "Fallback response";
}
}
@Test
public void shouldExecuteWithCircuitBreakerClosed() {
CircuitBreakerCommand command = new
CircuitBreakerCommand("ClosedBreaker", false);
String s = command.execute();
assertEquals("Some result", s);
HystrixCircuitBreaker breaker =
HystrixCircuitBreaker.Factory
.getInstance(command.getCommandKey());
assertTrue(breaker.allowRequest());
}
@Test
public void shouldExecuteWithCircuitBreakerOpen() {
CircuitBreakerCommand command = new
CircuitBreakerCommand("OpenBreaker", true);
String s = command.execute();
assertEquals("Fallback response", s);
HystrixCircuitBreaker breaker =
HystrixCircuitBreaker.Factory
.getInstance(command.getCommandKey());
assertFalse(breaker.allowRequest());
}
Load shedder (Thread pool)
public class LatentCommand extends HystrixCommand<String> {
private static final String COMMAND_GROUP = "default";
private final LatentResource resource;
public LatentCommand(LatentResource resource) {
super(HystrixCommandGroupKey.Factory.asKey(COMMAND_GROUP));
this.resource = resource;
}
@Override
protected String run() throws Exception {
return resource.getData();
}
@Override
protected String getFallback() {
return "Fallback triggered";
}
}
@Test
public void shouldShedLoad() {
List<Future<String>> l = new LinkedList<>();
LatentResource resource = new LatentResource(500L); // Make latent
// Use up all available threads
for (int i = 0; i < 10; i++)
l.add(new LatentCommand(resource).queue());
// Call will be rejected as thread pool is exhausted
String s = new LatentCommand(resource).execute();
assertEquals("Fallback triggered", s);
// All other calls succeed
for (Future<String> f : l)
assertEquals("Some value", get(f)); // wrapper for f.get()
}
Load shedder (Semaphore)
public class SemaphoreCommand extends HystrixCommand<String> {
private static final String COMMAND_GROUP = "default";
private final LatentResource resource;
public SemaphoreCommand(LatentResource resource) {
super(Setter.withGroupKey(
HystrixCommandGroupKey.Factory.asKey(COMMAND_GROUP))
.andCommandPropertiesDefaults(
HystrixCommandProperties.Setter()
.withExecutionIsolationStrategy(HystrixCommandProperties
.ExecutionIsolationStrategy.SEMAPHORE)));
this.resource = resource;
}
@Override
protected String run() throws Exception {
return resource.getData();
}
@Override
protected String getFallback() {
return "Fallback triggered";
}
}
private class SemaphoreCommandInvocation implements
java.util.concurrent.Callable<String> {
private final LatentResource resource;
public SemaphoreCommandInvocation(LatentResource resource) {
this.resource = resource;
}
@Override
public String call() throws Exception {
return new SemaphoreCommand(resource).execute();
}
}
@Test
public void shouldShedLoad() {
List<Future<String>> l = new LinkedList<>();
LatentResource resource = new LatentResource(500L); // Make latent
ExecutorService e = Executors.newFixedThreadPool(10);
// Use up all available semaphores
for (int i = 0; i < 10; i++)
l.add(e.submit(new SemaphoreCommandInvocation(resource)));
// Wait a moment to make sure all commands are started
pause(250L); // Wrapper around Thread.sleep()
// Call will be rejected as all semaphores are in use
String s = new SemaphoreCommand(resource).execute();
assertEquals("Fallback triggered", s);
// All other calls succeed
for (Future<String> f : l)
assertEquals("Some value", get(f));
}
Fail fast
public class FailFastCommand extends HystrixCommand<String> {
private static final String COMMAND_GROUP = "default";
private final boolean preCondition;
public FailFastCommand(boolean preCondition) {
super(HystrixCommandGroupKey.Factory.asKey(COMMAND_GROUP));
this.preCondition = preCondition;
}
@Override
protected String run() throws Exception {
if (!preCondition)
throw new RuntimeException(("Fail fast"));
return "Some value";
}
}
@Test
public void shouldSucceed() {
FailFastCommand command = new FailFastCommand(true);
String s = command.execute();
assertEquals("Some value", s);
}
@Test
public void shouldFailFast() {
FailFastCommand command = new FailFastCommand(false);
try {
String s = command.execute();
fail("Did not fail fast");
} catch (Exception e) {
assertEquals(HystrixRuntimeException.class, e.getClass());
assertEquals("Fail fast", e.getCause().getMessage());
}
}
Fail silent
public class FailSilentCommand extends HystrixCommand<String> {
private static final String COMMAND_GROUP = "default";
private final boolean preCondition;
public FailSilentCommand(boolean preCondition) {
super(HystrixCommandGroupKey.Factory.asKey(COMMAND_GROUP));
this.preCondition = preCondition;
}
@Override
protected String run() throws Exception {
if (!preCondition)
throw new RuntimeException(("Fail fast"));
return "Some value";
}
@Override
protected String getFallback() {
return null; // Turn into silent failure
}
}
@Test
public void shouldSucceed() {
FailSilentCommand command = new FailSilentCommand(true);
String s = command.execute();
assertEquals("Some value", s);
}
@Test
public void shouldFailSilent() {
FailSilentCommand command = new FailSilentCommand(false);
String s = "Test value";
try {
s = command.execute();
} catch (Exception e) {
fail("Did not fail silent");
}
assertNull(s);
}
Static fallback
public class StaticFallbackCommand extends HystrixCommand<String> {
private static final String COMMAND_GROUP = "default";
private final boolean preCondition;
public StaticFallbackCommand(boolean preCondition) {
super(HystrixCommandGroupKey.Factory.asKey(COMMAND_GROUP));
this.preCondition = preCondition;
}
@Override
protected String run() throws Exception {
if (!preCondition)
throw new RuntimeException(("Fail fast"));
return "Some value";
}
@Override
protected String getFallback() {
return "Some static fallback value"; // Static fallback
}
}
@Test
public void shouldSucceed() {
StaticFallbackCommand command = new StaticFallbackCommand(true);
String s = command.execute();
assertEquals("Some value", s);
}
@Test
public void shouldProvideStaticFallback() {
StaticFallbackCommand command = new StaticFallbackCommand(false);
String s = null;
try {
s = command.execute();
} catch (Exception e) {
fail("Did not fail silent");
}
assertEquals("Some static fallback value", s);
}
Cache fallback
public class CacheClient {
private final Map<String, String> map;
public CacheClient() {
map = new ConcurrentHashMap<>();
}
public void add(String key, String value) {
map.put(key, value);
}
public String get(String key) {
return map.get(key);
}
}
public class CacheCommand extends HystrixCommand<String> {
private static final String COMMAND_GROUP = "primary";
private final CacheClient cache;
private final boolean failPrimary;
private final String req;
public CacheCommand(CacheClient cache, boolean failPrimary,
String request) {
super(HystrixCommandGroupKey.Factory.asKey(COMMAND_GROUP));
this.cache = cache;
this.failPrimary = failPrimary;
this.req = request;
}
@Override
protected String run() throws Exception {
if (failPrimary)
throw new RuntimeException("Failure of primary");
String s = req + "-o";
cache.add(req, s);
return(s);
}
…
…
@Override
protected String getFallback() {
return "Cached: " + new FBCommand(cache, req).execute();
}
private static class FBCommand extends HystrixCommand<String> {
private static final String COMMAND_GROUP = "fallback";
private final CacheClient cache;
private final String request;
public FBCommand(CacheClient cache, String request) {
super(HystrixCommandGroupKey.Factory.asKey(COMMAND_GROUP));
this.cache = cache;
this.request = request;
}
@Override
protected String run() throws Exception {
return cache.get(request);
}
}
}
@Test
public void shouldExecuteWithoutCache() {
CacheClient cache = new CacheClient();
String s = new CacheCommand(cache, false, "ping”).execute();
assertEquals("ping-o", s);
}
@Test
public void shouldRetrieveValueFromCache() {
CacheClient cache = new CacheClient();
new CacheCommand(cache, false, "ping").execute();
String s = new CacheCommand(cache, true, "ping”).execute();
assertEquals("Cached: ping-o", s);
}
@Test
public void shouldNotRetrieveAnyValue() {
CacheClient cache = new CacheClient();
String s = new CacheCommand(cache, true, "ping”).execute();
assertEquals("Cached: null", s);
}
… and so on
Advanced features
Advanced Features

•  Request Caching
•  Request Collapsing
•  Plugins

Event Notifier, Metrics Publisher, Properties Strategy,
Concurrency Strategy, Command Execution Hook
•  Contributions

Metrics Event Stream, Metrics Publisher, Java Annotations,
Clojure Bindings, …
•  Dashboard
Source: https://github.com/Netflix/Hystrix/wiki/Dashboard
Source: https://github.com/Netflix/Hystrix/wiki/Dashboard
Further reading

1.  Hystrix Wiki,

https://github.com/Netflix/Hystrix/wiki
2.  Michael T. Nygard, Release It!,
Pragmatic Bookshelf, 2007
3.  Robert S. Hanmer,

Patterns for Fault Tolerant Software,
Wiley, 2007
4.  Andrew Tanenbaum, Marten van Steen,
Distributed Systems – Principles and
Paradigms,

Prentice Hall, 2nd Edition, 2006
Wrap-up

•  Resilient software design becomes a must
•  Hystrix is a resilience library
•  Provides isolation and latency control
•  Easy to start with
•  Yet some learning curve
•  Many fault-tolerance patterns implementable
•  Many configuration options
•  Customizable
•  Operations proven

Become a resilient software developer!
It‘s all about production!
@ufried
Uwe Friedrichsen | uwe.friedrichsen@codecentric.de | http://slideshare.net/ufried | http://ufried.tumblr.com
Resilience with Hystrix

More Related Content

What's hot

We Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End DevelopmentWe Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End DevelopmentAll Things Open
 
Prometheus (Monitorama 2016)
Prometheus (Monitorama 2016)Prometheus (Monitorama 2016)
Prometheus (Monitorama 2016)Brian Brazil
 
Terraform - Taming Modern Clouds
Terraform  - Taming Modern CloudsTerraform  - Taming Modern Clouds
Terraform - Taming Modern CloudsNic Jackson
 
Terraform modules restructured
Terraform modules restructuredTerraform modules restructured
Terraform modules restructuredAmi Mahloof
 
The Need for Async @ ScalaWorld
The Need for Async @ ScalaWorldThe Need for Async @ ScalaWorld
The Need for Async @ ScalaWorldKonrad Malawski
 
Atmosphere whitepaper
Atmosphere whitepaperAtmosphere whitepaper
Atmosphere whitepaperAnarkii17
 

What's hot (6)

We Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End DevelopmentWe Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End Development
 
Prometheus (Monitorama 2016)
Prometheus (Monitorama 2016)Prometheus (Monitorama 2016)
Prometheus (Monitorama 2016)
 
Terraform - Taming Modern Clouds
Terraform  - Taming Modern CloudsTerraform  - Taming Modern Clouds
Terraform - Taming Modern Clouds
 
Terraform modules restructured
Terraform modules restructuredTerraform modules restructured
Terraform modules restructured
 
The Need for Async @ ScalaWorld
The Need for Async @ ScalaWorldThe Need for Async @ ScalaWorld
The Need for Async @ ScalaWorld
 
Atmosphere whitepaper
Atmosphere whitepaperAtmosphere whitepaper
Atmosphere whitepaper
 

Similar to Resilience with Hystrix

Resilence patterns kr
Resilence patterns krResilence patterns kr
Resilence patterns krJisung Ahn
 
Vert.x - Reactive & Distributed [Devoxx version]
Vert.x - Reactive & Distributed [Devoxx version]Vert.x - Reactive & Distributed [Devoxx version]
Vert.x - Reactive & Distributed [Devoxx version]Orkhan Gasimov
 
Java APIs- The missing manual (concurrency)
Java APIs- The missing manual (concurrency)Java APIs- The missing manual (concurrency)
Java APIs- The missing manual (concurrency)Hendrik Ebbers
 
JavaOne 2017 - TestContainers: integration testing without the hassle
JavaOne 2017 - TestContainers: integration testing without the hassleJavaOne 2017 - TestContainers: integration testing without the hassle
JavaOne 2017 - TestContainers: integration testing without the hassleAnton Arhipov
 
Testing Java Code Effectively
Testing Java Code EffectivelyTesting Java Code Effectively
Testing Java Code EffectivelyAndres Almiray
 
Testing basics for developers
Testing basics for developersTesting basics for developers
Testing basics for developersAnton Udovychenko
 
Java util concurrent
Java util concurrentJava util concurrent
Java util concurrentRoger Xia
 
Fork and join framework
Fork and join frameworkFork and join framework
Fork and join frameworkMinh Tran
 
Architecting for Microservices Part 2
Architecting for Microservices Part 2Architecting for Microservices Part 2
Architecting for Microservices Part 2Elana Krasner
 
How to test infrastructure code: automated testing for Terraform, Kubernetes,...
How to test infrastructure code: automated testing for Terraform, Kubernetes,...How to test infrastructure code: automated testing for Terraform, Kubernetes,...
How to test infrastructure code: automated testing for Terraform, Kubernetes,...Yevgeniy Brikman
 
Cassandra Summit EU 2014 - Testing Cassandra Applications
Cassandra Summit EU 2014 - Testing Cassandra ApplicationsCassandra Summit EU 2014 - Testing Cassandra Applications
Cassandra Summit EU 2014 - Testing Cassandra ApplicationsChristopher Batey
 
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014FalafelSoftware
 
Breaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingBreaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingSteven Smith
 
Java design patterns
Java design patternsJava design patterns
Java design patternsShawn Brito
 
Java Concurrency, Memory Model, and Trends
Java Concurrency, Memory Model, and TrendsJava Concurrency, Memory Model, and Trends
Java Concurrency, Memory Model, and TrendsCarol McDonald
 
JRuby and Invokedynamic - Japan JUG 2015
JRuby and Invokedynamic - Japan JUG 2015JRuby and Invokedynamic - Japan JUG 2015
JRuby and Invokedynamic - Japan JUG 2015Charles Nutter
 
Introduction of failsafe
Introduction of failsafeIntroduction of failsafe
Introduction of failsafeSunghyouk Bae
 
MicroProfile: A Quest for a Lightweight and Modern Enterprise Java Platform
MicroProfile: A Quest for a Lightweight and Modern Enterprise Java PlatformMicroProfile: A Quest for a Lightweight and Modern Enterprise Java Platform
MicroProfile: A Quest for a Lightweight and Modern Enterprise Java PlatformMike Croft
 

Similar to Resilience with Hystrix (20)

Resilience mit Hystrix
Resilience mit HystrixResilience mit Hystrix
Resilience mit Hystrix
 
Resilence patterns kr
Resilence patterns krResilence patterns kr
Resilence patterns kr
 
Vert.x - Reactive & Distributed [Devoxx version]
Vert.x - Reactive & Distributed [Devoxx version]Vert.x - Reactive & Distributed [Devoxx version]
Vert.x - Reactive & Distributed [Devoxx version]
 
Java APIs- The missing manual (concurrency)
Java APIs- The missing manual (concurrency)Java APIs- The missing manual (concurrency)
Java APIs- The missing manual (concurrency)
 
JavaOne 2017 - TestContainers: integration testing without the hassle
JavaOne 2017 - TestContainers: integration testing without the hassleJavaOne 2017 - TestContainers: integration testing without the hassle
JavaOne 2017 - TestContainers: integration testing without the hassle
 
Testing Java Code Effectively
Testing Java Code EffectivelyTesting Java Code Effectively
Testing Java Code Effectively
 
Testing basics for developers
Testing basics for developersTesting basics for developers
Testing basics for developers
 
Java util concurrent
Java util concurrentJava util concurrent
Java util concurrent
 
Fork and join framework
Fork and join frameworkFork and join framework
Fork and join framework
 
Architecting for Microservices Part 2
Architecting for Microservices Part 2Architecting for Microservices Part 2
Architecting for Microservices Part 2
 
Curator intro
Curator introCurator intro
Curator intro
 
How to test infrastructure code: automated testing for Terraform, Kubernetes,...
How to test infrastructure code: automated testing for Terraform, Kubernetes,...How to test infrastructure code: automated testing for Terraform, Kubernetes,...
How to test infrastructure code: automated testing for Terraform, Kubernetes,...
 
Cassandra Summit EU 2014 - Testing Cassandra Applications
Cassandra Summit EU 2014 - Testing Cassandra ApplicationsCassandra Summit EU 2014 - Testing Cassandra Applications
Cassandra Summit EU 2014 - Testing Cassandra Applications
 
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014
 
Breaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingBreaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit Testing
 
Java design patterns
Java design patternsJava design patterns
Java design patterns
 
Java Concurrency, Memory Model, and Trends
Java Concurrency, Memory Model, and TrendsJava Concurrency, Memory Model, and Trends
Java Concurrency, Memory Model, and Trends
 
JRuby and Invokedynamic - Japan JUG 2015
JRuby and Invokedynamic - Japan JUG 2015JRuby and Invokedynamic - Japan JUG 2015
JRuby and Invokedynamic - Japan JUG 2015
 
Introduction of failsafe
Introduction of failsafeIntroduction of failsafe
Introduction of failsafe
 
MicroProfile: A Quest for a Lightweight and Modern Enterprise Java Platform
MicroProfile: A Quest for a Lightweight and Modern Enterprise Java PlatformMicroProfile: A Quest for a Lightweight and Modern Enterprise Java Platform
MicroProfile: A Quest for a Lightweight and Modern Enterprise Java Platform
 

More from Uwe Friedrichsen

Timeless design in a cloud-native world
Timeless design in a cloud-native worldTimeless design in a cloud-native world
Timeless design in a cloud-native worldUwe Friedrichsen
 
The hitchhiker's guide for the confused developer
The hitchhiker's guide for the confused developerThe hitchhiker's guide for the confused developer
The hitchhiker's guide for the confused developerUwe Friedrichsen
 
Digitization solutions - A new breed of software
Digitization solutions - A new breed of softwareDigitization solutions - A new breed of software
Digitization solutions - A new breed of softwareUwe Friedrichsen
 
Real-world consistency explained
Real-world consistency explainedReal-world consistency explained
Real-world consistency explainedUwe Friedrichsen
 
The 7 quests of resilient software design
The 7 quests of resilient software designThe 7 quests of resilient software design
The 7 quests of resilient software designUwe Friedrichsen
 
Excavating the knowledge of our ancestors
Excavating the knowledge of our ancestorsExcavating the knowledge of our ancestors
Excavating the knowledge of our ancestorsUwe Friedrichsen
 
The truth about "You build it, you run it!"
The truth about "You build it, you run it!"The truth about "You build it, you run it!"
The truth about "You build it, you run it!"Uwe Friedrichsen
 
The promises and perils of microservices
The promises and perils of microservicesThe promises and perils of microservices
The promises and perils of microservicesUwe Friedrichsen
 
Resilient Functional Service Design
Resilient Functional Service DesignResilient Functional Service Design
Resilient Functional Service DesignUwe Friedrichsen
 
Resilience reloaded - more resilience patterns
Resilience reloaded - more resilience patternsResilience reloaded - more resilience patterns
Resilience reloaded - more resilience patternsUwe Friedrichsen
 
DevOps is not enough - Embedding DevOps in a broader context
DevOps is not enough - Embedding DevOps in a broader contextDevOps is not enough - Embedding DevOps in a broader context
DevOps is not enough - Embedding DevOps in a broader contextUwe Friedrichsen
 
Towards complex adaptive architectures
Towards complex adaptive architecturesTowards complex adaptive architectures
Towards complex adaptive architecturesUwe Friedrichsen
 
Conway's law revisited - Architectures for an effective IT
Conway's law revisited - Architectures for an effective ITConway's law revisited - Architectures for an effective IT
Conway's law revisited - Architectures for an effective ITUwe Friedrichsen
 
Microservices - stress-free and without increased heart attack risk
Microservices - stress-free and without increased heart attack riskMicroservices - stress-free and without increased heart attack risk
Microservices - stress-free and without increased heart attack riskUwe Friedrichsen
 

More from Uwe Friedrichsen (20)

Timeless design in a cloud-native world
Timeless design in a cloud-native worldTimeless design in a cloud-native world
Timeless design in a cloud-native world
 
Deep learning - a primer
Deep learning - a primerDeep learning - a primer
Deep learning - a primer
 
Life after microservices
Life after microservicesLife after microservices
Life after microservices
 
The hitchhiker's guide for the confused developer
The hitchhiker's guide for the confused developerThe hitchhiker's guide for the confused developer
The hitchhiker's guide for the confused developer
 
Digitization solutions - A new breed of software
Digitization solutions - A new breed of softwareDigitization solutions - A new breed of software
Digitization solutions - A new breed of software
 
Real-world consistency explained
Real-world consistency explainedReal-world consistency explained
Real-world consistency explained
 
The 7 quests of resilient software design
The 7 quests of resilient software designThe 7 quests of resilient software design
The 7 quests of resilient software design
 
Excavating the knowledge of our ancestors
Excavating the knowledge of our ancestorsExcavating the knowledge of our ancestors
Excavating the knowledge of our ancestors
 
The truth about "You build it, you run it!"
The truth about "You build it, you run it!"The truth about "You build it, you run it!"
The truth about "You build it, you run it!"
 
The promises and perils of microservices
The promises and perils of microservicesThe promises and perils of microservices
The promises and perils of microservices
 
Resilient Functional Service Design
Resilient Functional Service DesignResilient Functional Service Design
Resilient Functional Service Design
 
Watch your communication
Watch your communicationWatch your communication
Watch your communication
 
Life, IT and everything
Life, IT and everythingLife, IT and everything
Life, IT and everything
 
Resilience reloaded - more resilience patterns
Resilience reloaded - more resilience patternsResilience reloaded - more resilience patterns
Resilience reloaded - more resilience patterns
 
DevOps is not enough - Embedding DevOps in a broader context
DevOps is not enough - Embedding DevOps in a broader contextDevOps is not enough - Embedding DevOps in a broader context
DevOps is not enough - Embedding DevOps in a broader context
 
Production-ready Software
Production-ready SoftwareProduction-ready Software
Production-ready Software
 
Towards complex adaptive architectures
Towards complex adaptive architecturesTowards complex adaptive architectures
Towards complex adaptive architectures
 
Conway's law revisited - Architectures for an effective IT
Conway's law revisited - Architectures for an effective ITConway's law revisited - Architectures for an effective IT
Conway's law revisited - Architectures for an effective IT
 
Microservices - stress-free and without increased heart attack risk
Microservices - stress-free and without increased heart attack riskMicroservices - stress-free and without increased heart attack risk
Microservices - stress-free and without increased heart attack risk
 
Patterns of resilience
Patterns of resiliencePatterns of resilience
Patterns of resilience
 

Recently uploaded

Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piececharlottematthew16
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionDilum Bandara
 

Recently uploaded (20)

Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piece
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An Introduction
 

Resilience with Hystrix

  • 1. Resilience with Hystrix An introduction Uwe Friedrichsen, codecentric AG, 2014
  • 2. @ufried Uwe Friedrichsen | uwe.friedrichsen@codecentric.de | http://slideshare.net/ufried | http://ufried.tumblr.com
  • 3. It‘s all about production!
  • 5. re•sil•ience (rɪˈzɪl yəns) also re•sil′ien•cy, n. 1.  the power or ability to return to the original form, position, etc., after being bent, compressed, or stretched; elasticity. 2.  ability to recover readily from illness, depression, adversity, or the like; buoyancy. Random House Kernerman Webster's College Dictionary, © 2010 K Dictionaries Ltd. Copyright 2005, 1997, 1991 by Random House, Inc. All rights reserved. http://www.thefreedictionary.com/resilience
  • 6.
  • 7. Implemented patterns •  Timeout •  Circuit breaker •  Load shedder
  • 8. Supported patterns •  Bulkheads
 (a.k.a. Failure Units) •  Fail fast •  Fail silently •  Graceful degradation of service •  Failover •  Escalation •  Retry •  ...
  • 9. That‘s been enough theory Give us some code – now!
  • 12. public class HelloCommand extends HystrixCommand<String> { private static final String COMMAND_GROUP = "default"; private final String name; public HelloCommand(String name) { super(HystrixCommandGroupKey.Factory.asKey(COMMAND_GROUP)); this.name = name; } @Override protected String run() throws Exception { return "Hello, " + name; } }
  • 13. @Test public void shouldGreetWorld() { String result = new HelloCommand("World").execute(); assertEquals("Hello, World", result); }
  • 15. @Test public void shouldExecuteSynchronously() { String s = new HelloCommand("Bob").execute(); assertEquals("Hello, Bob", s); }
  • 17. @Test public void shouldExecuteAsynchronously() { Future<String> f = new HelloCommand("Alice").queue(); String s = null; try { s = f.get(); } catch (InterruptedException | ExecutionException e) { // Handle Future.get() exceptions here } assertEquals("Hello, Alice", s); }
  • 19. @Test public void shouldExecuteReactiveSimple() { Observable<String> observable = new HelloCommand("Alice").observe(); String s = observable.toBlockingObservable().single(); assertEquals("Hello, Alice", s); }
  • 21. public class CommandHelloObserver implements Observer<String> { // Needed for communication between observer and test case private final AtomicReference<String> aRef; private final Semaphore semaphore; public CommandHelloObserver(AtomicReference<String> aRef, Semaphore semaphore) { this.aRef = aRef; this.semaphore = semaphore; } @Override public void onCompleted() { // Not needed here } @Override public void onError(Throwable e) { // Not needed here } @Override public void onNext(String s) { aRef.set(s); semaphore.release(); } }
  • 22. @Test public void shouldExecuteReactiveFull() { // Needed for communication between observer and test case AtomicReference<String> aRef = new AtomicReference<>(); Semaphore semaphore = new Semaphore(0); Observable<String> observable = new HelloCommand("Bob").observe(); Observer<String> observer = new CommandHelloObserver(aRef, semaphore); observable.subscribe(observer); // Wait until observer received a result try { semaphore.acquire(); } catch (InterruptedException e) { // Handle exceptions here } String s = aRef.get(); assertEquals("Hello, Bob", s); }
  • 24. public class FallbackCommand extends HystrixCommand<String> { private static final String COMMAND_GROUP = "default"; public FallbackCommand() { super(HystrixCommandGroupKey.Factory.asKey(COMMAND_GROUP)); } @Override protected String run() throws Exception { throw new RuntimeException("I will always fail"); } @Override protected String getFallback() { return "Powered by fallback"; } }
  • 25. @Test public void shouldGetFallbackResponse() { String s = new FallbackCommand().execute(); assertEquals("Powered by fallback", s); }
  • 27. public class ErrorPropagationCommand extends HystrixCommand<String> { private static final String COMMAND_GROUP = "default"; protected ErrorPropagationCommand() { super(HystrixCommandGroupKey.Factory.asKey(COMMAND_GROUP)); } @Override protected String run() throws Exception { throw new HystrixBadRequestException("I fail differently", new RuntimeException("I will always fail")); } @Override protected String getFallback() { return "Powered by fallback"; } }
  • 28. @Test public void shouldGetFallbackResponse() { String s = null; try { s = new ErrorPropagationCommand().execute(); fail(); // Just to make sure } catch (HystrixBadRequestException e) { assertEquals("I will fail differently", e.getMessage()); assertEquals("I will always fail", e.getCause().getMessage()); } assertNull(s); // Fallback is not triggered }
  • 34. Configuration •  Based on Archaius by Netflix
 which extends the Apache Commons Configuration Library •  Four levels of precedence 1.  Global default from code 2.  Dynamic global default property 3.  Instance default from code 4.  Dynamic instance property Provides many configuration & tuning options
  • 35. Configuration – Some examples •  hystrix.command.*.execution.isolation.strategy
 Either “THREAD” or “SEMAPHORE” (Default: THREAD) •  hystrix.command.*.execution.isolation.thread.timeoutInMilliseconds
 Time to wait for the run() method to complete (Default: 1000) •  h.c.*.execution.isolation.semaphore.maxConcurrentRequests
 Maximum number of concurrent requests when using semaphores (Default: 10) •  hystrix.command.*.circuitBreaker.errorThresholdPercentage
 Error percentage at which the breaker trips open (Default: 50) •  hystrix.command.*.circuitBreaker.sleepWindowInMilliseconds
 Time to wait before attempting to reset the breaker after tripping (Default: 5000) * must be either “default” or the command key name
  • 36. Configuration – More examples •  hystrix.threadpool.*.coreSize
 Maximum number of concurrent requests when using thread pools (Default: 10) •  hystrix.threadpool.*.maxQueueSize
 Maximum LinkedBlockingQueue size - -1 for using SynchronousQueue (Default: -1) •  hystrix.threadpool.default.queueSizeRejectionThreshold
 Queue size rejection threshold (Default: 5) … and many more * must be either “default” or the thread pool key name
  • 39. public class LatentResource { private final long latency; public LatentResource(long latency) { this.latency = ((latency < 0L) ? 0L : latency); } public String getData() { addLatency(); // This is the important part return "Some value”; } private void addLatency() { try { Thread.sleep(latency); } catch (InterruptedException e) { // We do not care about this here } } }
  • 40. public class TimeoutCommand extends HystrixCommand<String> { private static final String COMMAND_GROUP = "default"; private final LatentResource resource; public TimeoutCommand(int timeout, LatentResource resource) { super(Setter.withGroupKey( HystrixCommandGroupKey.Factory.asKey(COMMAND_GROUP)) .andCommandPropertiesDefaults( HystrixCommandProperties.Setter() .withExecutionIsolationThreadTimeoutInMilliseconds( timeout))); this.resource = resource; } @Override protected String run() throws Exception { return resource.getData(); } @Override protected String getFallback() { return "Resource timed out"; } }
  • 41. @Test public void shouldGetNormalResponse() { LatentResource resource = new LatentResource(50L); TimeoutCommand command = new TimeoutCommand(100, resource); String s = command.execute(); assertEquals("Some value", s); } @Test public void shouldGetFallbackResponse() { LatentResource resource = new LatentResource(150L); TimeoutCommand command = new TimeoutCommand(100, resource); String s = command.execute(); assertEquals("Resource timed out", s); }
  • 43. public class CircuitBreakerCommand extends HystrixCommand<String> { private static final String COMMAND_GROUP = "default"; public CircuitBreakerCommand(String name, boolean open) { super(Setter.withGroupKey( HystrixCommandGroupKey.Factory.asKey(COMMAND_GROUP)) .andCommandKey(HystrixCommandKey.Factory.asKey(name)) .andCommandPropertiesDefaults( HystrixCommandProperties.Setter() .withCircuitBreakerForceOpen(open))); } @Override protected String run() throws Exception { return("Some result"); } @Override protected String getFallback() { return "Fallback response"; } }
  • 44. @Test public void shouldExecuteWithCircuitBreakerClosed() { CircuitBreakerCommand command = new CircuitBreakerCommand("ClosedBreaker", false); String s = command.execute(); assertEquals("Some result", s); HystrixCircuitBreaker breaker = HystrixCircuitBreaker.Factory .getInstance(command.getCommandKey()); assertTrue(breaker.allowRequest()); }
  • 45. @Test public void shouldExecuteWithCircuitBreakerOpen() { CircuitBreakerCommand command = new CircuitBreakerCommand("OpenBreaker", true); String s = command.execute(); assertEquals("Fallback response", s); HystrixCircuitBreaker breaker = HystrixCircuitBreaker.Factory .getInstance(command.getCommandKey()); assertFalse(breaker.allowRequest()); }
  • 47. public class LatentCommand extends HystrixCommand<String> { private static final String COMMAND_GROUP = "default"; private final LatentResource resource; public LatentCommand(LatentResource resource) { super(HystrixCommandGroupKey.Factory.asKey(COMMAND_GROUP)); this.resource = resource; } @Override protected String run() throws Exception { return resource.getData(); } @Override protected String getFallback() { return "Fallback triggered"; } }
  • 48. @Test public void shouldShedLoad() { List<Future<String>> l = new LinkedList<>(); LatentResource resource = new LatentResource(500L); // Make latent // Use up all available threads for (int i = 0; i < 10; i++) l.add(new LatentCommand(resource).queue()); // Call will be rejected as thread pool is exhausted String s = new LatentCommand(resource).execute(); assertEquals("Fallback triggered", s); // All other calls succeed for (Future<String> f : l) assertEquals("Some value", get(f)); // wrapper for f.get() }
  • 50. public class SemaphoreCommand extends HystrixCommand<String> { private static final String COMMAND_GROUP = "default"; private final LatentResource resource; public SemaphoreCommand(LatentResource resource) { super(Setter.withGroupKey( HystrixCommandGroupKey.Factory.asKey(COMMAND_GROUP)) .andCommandPropertiesDefaults( HystrixCommandProperties.Setter() .withExecutionIsolationStrategy(HystrixCommandProperties .ExecutionIsolationStrategy.SEMAPHORE))); this.resource = resource; } @Override protected String run() throws Exception { return resource.getData(); } @Override protected String getFallback() { return "Fallback triggered"; } }
  • 51. private class SemaphoreCommandInvocation implements java.util.concurrent.Callable<String> { private final LatentResource resource; public SemaphoreCommandInvocation(LatentResource resource) { this.resource = resource; } @Override public String call() throws Exception { return new SemaphoreCommand(resource).execute(); } }
  • 52. @Test public void shouldShedLoad() { List<Future<String>> l = new LinkedList<>(); LatentResource resource = new LatentResource(500L); // Make latent ExecutorService e = Executors.newFixedThreadPool(10); // Use up all available semaphores for (int i = 0; i < 10; i++) l.add(e.submit(new SemaphoreCommandInvocation(resource))); // Wait a moment to make sure all commands are started pause(250L); // Wrapper around Thread.sleep() // Call will be rejected as all semaphores are in use String s = new SemaphoreCommand(resource).execute(); assertEquals("Fallback triggered", s); // All other calls succeed for (Future<String> f : l) assertEquals("Some value", get(f)); }
  • 54. public class FailFastCommand extends HystrixCommand<String> { private static final String COMMAND_GROUP = "default"; private final boolean preCondition; public FailFastCommand(boolean preCondition) { super(HystrixCommandGroupKey.Factory.asKey(COMMAND_GROUP)); this.preCondition = preCondition; } @Override protected String run() throws Exception { if (!preCondition) throw new RuntimeException(("Fail fast")); return "Some value"; } }
  • 55. @Test public void shouldSucceed() { FailFastCommand command = new FailFastCommand(true); String s = command.execute(); assertEquals("Some value", s); } @Test public void shouldFailFast() { FailFastCommand command = new FailFastCommand(false); try { String s = command.execute(); fail("Did not fail fast"); } catch (Exception e) { assertEquals(HystrixRuntimeException.class, e.getClass()); assertEquals("Fail fast", e.getCause().getMessage()); } }
  • 57. public class FailSilentCommand extends HystrixCommand<String> { private static final String COMMAND_GROUP = "default"; private final boolean preCondition; public FailSilentCommand(boolean preCondition) { super(HystrixCommandGroupKey.Factory.asKey(COMMAND_GROUP)); this.preCondition = preCondition; } @Override protected String run() throws Exception { if (!preCondition) throw new RuntimeException(("Fail fast")); return "Some value"; } @Override protected String getFallback() { return null; // Turn into silent failure } }
  • 58. @Test public void shouldSucceed() { FailSilentCommand command = new FailSilentCommand(true); String s = command.execute(); assertEquals("Some value", s); } @Test public void shouldFailSilent() { FailSilentCommand command = new FailSilentCommand(false); String s = "Test value"; try { s = command.execute(); } catch (Exception e) { fail("Did not fail silent"); } assertNull(s); }
  • 60. public class StaticFallbackCommand extends HystrixCommand<String> { private static final String COMMAND_GROUP = "default"; private final boolean preCondition; public StaticFallbackCommand(boolean preCondition) { super(HystrixCommandGroupKey.Factory.asKey(COMMAND_GROUP)); this.preCondition = preCondition; } @Override protected String run() throws Exception { if (!preCondition) throw new RuntimeException(("Fail fast")); return "Some value"; } @Override protected String getFallback() { return "Some static fallback value"; // Static fallback } }
  • 61. @Test public void shouldSucceed() { StaticFallbackCommand command = new StaticFallbackCommand(true); String s = command.execute(); assertEquals("Some value", s); } @Test public void shouldProvideStaticFallback() { StaticFallbackCommand command = new StaticFallbackCommand(false); String s = null; try { s = command.execute(); } catch (Exception e) { fail("Did not fail silent"); } assertEquals("Some static fallback value", s); }
  • 63. public class CacheClient { private final Map<String, String> map; public CacheClient() { map = new ConcurrentHashMap<>(); } public void add(String key, String value) { map.put(key, value); } public String get(String key) { return map.get(key); } }
  • 64. public class CacheCommand extends HystrixCommand<String> { private static final String COMMAND_GROUP = "primary"; private final CacheClient cache; private final boolean failPrimary; private final String req; public CacheCommand(CacheClient cache, boolean failPrimary, String request) { super(HystrixCommandGroupKey.Factory.asKey(COMMAND_GROUP)); this.cache = cache; this.failPrimary = failPrimary; this.req = request; } @Override protected String run() throws Exception { if (failPrimary) throw new RuntimeException("Failure of primary"); String s = req + "-o"; cache.add(req, s); return(s); } …
  • 65. … @Override protected String getFallback() { return "Cached: " + new FBCommand(cache, req).execute(); } private static class FBCommand extends HystrixCommand<String> { private static final String COMMAND_GROUP = "fallback"; private final CacheClient cache; private final String request; public FBCommand(CacheClient cache, String request) { super(HystrixCommandGroupKey.Factory.asKey(COMMAND_GROUP)); this.cache = cache; this.request = request; } @Override protected String run() throws Exception { return cache.get(request); } } }
  • 66. @Test public void shouldExecuteWithoutCache() { CacheClient cache = new CacheClient(); String s = new CacheCommand(cache, false, "ping”).execute(); assertEquals("ping-o", s); } @Test public void shouldRetrieveValueFromCache() { CacheClient cache = new CacheClient(); new CacheCommand(cache, false, "ping").execute(); String s = new CacheCommand(cache, true, "ping”).execute(); assertEquals("Cached: ping-o", s); } @Test public void shouldNotRetrieveAnyValue() { CacheClient cache = new CacheClient(); String s = new CacheCommand(cache, true, "ping”).execute(); assertEquals("Cached: null", s); }
  • 69. Advanced Features •  Request Caching •  Request Collapsing •  Plugins
 Event Notifier, Metrics Publisher, Properties Strategy, Concurrency Strategy, Command Execution Hook •  Contributions
 Metrics Event Stream, Metrics Publisher, Java Annotations, Clojure Bindings, … •  Dashboard
  • 72. Further reading 1.  Hystrix Wiki,
 https://github.com/Netflix/Hystrix/wiki 2.  Michael T. Nygard, Release It!, Pragmatic Bookshelf, 2007 3.  Robert S. Hanmer,
 Patterns for Fault Tolerant Software, Wiley, 2007 4.  Andrew Tanenbaum, Marten van Steen, Distributed Systems – Principles and Paradigms,
 Prentice Hall, 2nd Edition, 2006
  • 73. Wrap-up •  Resilient software design becomes a must •  Hystrix is a resilience library •  Provides isolation and latency control •  Easy to start with •  Yet some learning curve •  Many fault-tolerance patterns implementable •  Many configuration options •  Customizable •  Operations proven Become a resilient software developer!
  • 74. It‘s all about production!
  • 75. @ufried Uwe Friedrichsen | uwe.friedrichsen@codecentric.de | http://slideshare.net/ufried | http://ufried.tumblr.com