-
Notifications
You must be signed in to change notification settings - Fork 11
Hystrix Microservice Provider
Hystrix Microservice Provider allows developers to easily add fault tolerance mechanisms to their projects. It uses Hystrix latency and fault tolerance library in the background and provides simple annotation-based configuration.
There are two different types of annotations which can be used to configure Hystrix in SilverWare – high-level and low-level. Both of them can be used to configure Hystrix per microservice method using configuration interface. Moreover, high-level annotations can also be used directly on an injection point and configure Hystrix the same way for all methods of the injected microservice.
The presence of any of these annotations (except for CacheKey) will automatically activate Hystrix and wrap all microservice calls in Hystrix commands. Otherwise, all method calls will be handled as usual even though Hystrix Microservice Provider dependency is added to a project.
High-level annotations provide basic configuration of fault tolerance mechanisms that should be sufficient for most use cases. The easiest way how to apply those mechanisms is to put these annotations directly on an injection point. In that case all method calls will use the same Hystrix configuration.
@Microservice
public class ResilientMicroservice {
@Inject
@CircuitBreaker
@MicroserviceReference
private FailingMicroservice failingMicroservice;
}
The other way how to use high-level annotations is to put them on a configuration interface. This approach offers more fine-grained configuration since fault tolerance mechanisms can be configured differently for each method. High-level annotations can be put both on interface type definition and its methods. While the former configures Hystrix for all methods, the latter overrides these settings for a specific method.
@Microservice
public class ResilientMicroservice {
@Inject
@HystrixConfig(FailingMicroserviceConfig.class)
@MicroserviceReference
private FailingMicroservice failingMicroservice;
}
@CircuitBreaker
public interface FailingMicroserviceConfig extends FailingMicroservice {
@Timeout
String slowMethod();
@Cached
int cachedMethod(int number);
}
@Cached annotation activates Hystrix request caching. If this mechanism is turned on, only the first request is executed and all others with the same cache key receive values from the cache. The cache key is created from the service name, the method name and the actual values of method parameters so a value from the cache is only received when exactly the same call is made multiple times.
...
@Inject
@Cached
@MicroserviceReference
private CachedMicroservice cachedMicroservice;
...
@CircuitBreaker annotation turns on Hystrix circuit breaker implementation and can be configured by the following three parameters:
- errorPercentage — error threshold percentage (default: 50)
- requestVolume — request volume threshold (default: 20)
- sleepWindow — sleep window in milliseconds (default: 5000)
...
@Inject
@CircuitBreaker(errorPercentage = 35, requestVolume = 10, sleepWindow = 7500)
@MicroserviceReference
private FailingMicroservice failingMicroservice;
...
@Fail annotation specifies exceptions which are ignored by Hystrix and re-thrown on the caller’s side. It takes an array of exception classes as a parameter. These exceptions will be completely ignored by Hystrix fault tolerance mechanisms as if the calls have succeeded.
...
@Inject
@Fail({IllegalArgumentException.class, UnsupportedOperationException.class})
@MicroserviceReference
private FailingMicroservice failingMicroservice;
...
@ThreadPool annotation sets the name and the size of a thread pool used for the execution of service calls.
If the name is not set, the name of the called microservice is used.
The default number of threads in a thread pool is 10
.
These thread pools are managed by Hystrix and are used with the default values even if this annotation is not present. It is not recommended to use the same thread pool for different services since problems with one service can then negatively influence the other ones (see Bulkheads stability pattern in the book Release It! by Michael T. Nygard).
...
@Inject
@ThreadPool(name = "myThreadPool", size = 42)
@MicroserviceReference
private FailingMicroservice failingMicroservice;
...
@Timeout annotation sets timeout for remote calls. The time value can be changed but the default one is 1000ms. If this annotation is present, all service calls that take longer to execute than a specified timeout will be interrupted and an exception will be thrown.
...
@Inject
@Timeout(2000)
@MicroserviceReference
private SlowMicroservice slowMicroservice;
...
Low-level annotations allow more flexibility than the high-level ones. Using them it is possible to directly change the configuration properties of Hystrix commands.
These annotations are inspired by those from Hystrix Javanica project. It is not possible to directly use Javanica and its annotations since it would add many unnecessary dependencies to SilverWare project.
@DefaultProperties annotation configures Hystrix on class level. The same settings are applied to all methods of a given service.
This annotation provides the following configuration properties:
- groupKey — default command group name
- threadPoolKey — default thread pool name
- commandProperties — Hystrix command properties
- threadPoolProperties — Hystrix thread pool properties
- ignoredExceptions — exceptions to be ignored by Hystrix
@HystrixCommand annotation configures Hystrix on method level.
For a given method it can alter configuration properties set by @DefaultProperties annotation.
It contains the same parameters as @DefaultProperties annotation and additional commandKey
parameter specifying command name for monitoring, circuit-breakers, metrics publishing, caching and other such uses.
The default value for commandKey
is:
callingMicroservice:injectionField:calledMethod
@HystrixProperty annotation specifies command properties and thread pool properties in @DefaultProperties and @HystrixCommand annotations. It has the following parameters:
- name — property name defined by Hystrix
- value — property value
SilverWare provides the names of all properties in constants in CommandProperties
and ThreadPoolProperties
interfaces.
@CacheKey annotation can be put on method parameters to specify which of them will be used for request caching. The other parameters will be ignored when storing the return value of the method in the cache. If no parameter is annotated with this annotation, all parameters will be used as a cache key.
Configuration interface is an extended microservice interface which has Hystrix configuration annotations on its methods. Both high-level and low-level annotations can be used.
The best way to define such an interface is to extend the one used on an injection point and override its methods. Annotations can be put both on the interface itself and on the methods.
public interface MyService {
int slowCall();
int cachedCall();
}
@CircuitBreaker
public interface MyServiceHystrixConfig extends MyService {
@Timeout
int slowCall();
@Cached
int cachedCall();
}
This interface needs to be referenced on an injection point so SilverWare will know where to find Hystrix configuration. @HystrixConfig annotation can be used for this purpose.
...
@Inject
@MicroserviceReference
@HystrixConfig(MyServiceHystrixConfig.class)
MyService myService;
...
SilverWare provides a fallback mechanism in order to support graceful degradation when a primary method call fails. It can be used regardless of which annotations is Hystrix configured by.
An alternative implementation of a given microservice needs to be provided and annotated with @Fallback qualifier. It has to be the implementation of the same interface as is used on an injection point. It is highly recommended not to execute any complicated logic in fallback methods and have a fallback microservice available locally on the same machine from which the original microservice is called to always be able to quickly and reliably return some value.
The methods where providing a fallback is not desired need to throw UnsupportedOperationException
so Hystrix will ignore them and throw the original exception from the primary method.
@Microservice
public class ResilientMicroservice {
@Inject
@CircuitBreaker
@MicroserviceReference
private FailingMicroservice failingMicroservice;
}
public interface FailingMicroservice {
int tryWithFallback();
String tryWithoutFallback(int param);
}
@Microservice
public class FailingMicroserviceImpl implements FailingMicroservice {
...
public int tryWithFallback() {
return calculate();
}
public String tryWithoutFallback(int param) {
return process(param);
}
...
}
@Fallback
@Microservice
public class FailingMicroserviceFallback implements FailingMicroservice {
public int tryWithFallback() {
return 0;
}
public String tryWithoutFallback(int param) {
throw new UnsupportedOperationException();
}
}
Hystrix Microservice Provider can be set up to publish Hystrix metrics using Hystrix event metrics stream.
There are two system properties which can be used to configure this provider:
-
silverware.hystrix.metrics.enabled
— activates Hystrix metrics stream deployment (default: false) -
silverware.hystrix.metrics.path
— path to Hystrix metrics stream (default: hystrix.stream)
If the metrics are deployed, they can be found on http://localhost:8080/hystrix.stream
by default.
Hystrix Dashboard is a simple web application which allows you to monitor Hystrix metrics in real time. It can be configured to consume Hystrix event metrics stream produced by Hystrix Microservice Provider.
Hystrix Microservice Provider depends on the following providers: