-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Plugins
- Plugins
- Plugin Types
- Event Notifier
- Metrics Publisher
- Properties Strategy
- Concurrency Strategy
- Command Execution Hook
- How to Use
- Abstract vs. Interface
You can modify the behavior of Hystrix, or add additional behavior to it, by implementing plugins.
You register these plugins by means of the HystrixPlugins
service. Hystrix will then apply them to all HystrixCommand
, HystrixObservableCommand
, and HystrixCollapser
implementations, overriding all others.
Following are introductions to each of the different plugins that you can implement (the Javadocs contain more detail):
Events that occur during HystrixCommand
and HystrixObservableCommand
execution are trigged on the HystrixEventNotifier
to give an opportunity for alerting and statistics-collection.
Each instance of metrics being captured (such as for all HystrixCommands
with a given HystrixCommandKey
) will ask the HystrixMetricsPublisher
for an implementation and initialize it.
This gives the implementation the opportunity to receive the metrics data objects and start a background process for doing something with the metrics such as publishing them to a persistent store.
The default implementation does not publish them anywhere.
If you wish to use Servo, which is an in-memory system that supports various mechanisms of retrieving the data such as through pollers or JMX, please see the documentation at https://github.com/Netflix/Hystrix/tree/master/hystrix-contrib/hystrix-servo-metrics-publisher
If you implement a custom HystrixPropertiesStrategy
, this gives you full control over how properties are defined for the system.
The default implementation uses Archaius.
Hystrix uses implementations of ThreadLocal
, Callable
, Runnable
, ThreadPoolExecutor
, and BlockingQueue
as part its thread isolation and request-scoped functionality.
By default Hystrix has implementations that work “out of the box” but many environments (including Netflix) desire the use of alternatives so this plugin allows injecting custom implementations or decorating behavior.
You can implement the HystrixConcurrencyStrategy
class with the following:
-
The
getThreadPool()
andgetBlockingQueue()
methods are straightforward options that inject the implementation of your choice, or just a decorated version with extra logging and metrics. -
The
wrapCallable()
method allows you to decorate everyCallable
executed by Hystrix. This can be essential to systems that rely uponThreadLocal
state for application functionality. The wrappingCallable
can capture and copy state from parent to child thread as needed. -
The
getRequestVariable()
method expects an implementation ofHystrixRequestVariable<T>
that functions like aThreadLocal
except scoped to the request — available on all threads within the request. Generally it will be easier and sufficient to just use theHystrixRequestContext
with its own default implementation ofHystrixRequestVariable
.
A HystrixCommandExecutionHook
implementation gives you access to the execution lifecycle of a HystrixInvokable
(HystrixCommand
or HystrixObservableCommand
) so that you can inject behavior, logging, override responses, alter thread state, etc. You do this by overriding one or more of the following hooks:
HystrixCommandExecutionHook method |
when Hystrix calls the method |
---|---|
onStart |
before the HystrixInvokable begins executing |
onEmit |
whenever the HystrixInvokable emits a value |
onError |
if the HystrixInvokable fails with an exception |
onSuccess |
if the HystrixInvokable completes successfully |
onThreadStart |
at the start of thread execution if the HystrixInvokable is a HystrixCommand executed using the THREAD ExecutionIsolationStrategy
|
onThreadComplete |
at the completion of thread execution if the HystrixInvokable is a HystrixCommand executed using the THREAD ExecutionIsolationStrategy
|
onExecutionStart |
when the user-defined execution method in the HystrixInvokable begins |
onExecutionEmit |
whenever the user-defined execution method in the HystrixInvokable emits a value |
onExecutionError |
when the user-defined execution method in the HystrixInvokable fails with an exception |
onExecutionSuccess |
when the user-defined execution method in the HystrixInvokable completes successfully |
onFallbackStart |
if the HystrixInvokable attempts to call the fallback method |
onFallbackEmit |
whenever the fallback method in the HystrixInvokable emits a value |
onFallbackError |
if the fallback method in the HystrixInvokable fails with an exception or does not exist when a call attempt is made |
onFallbackSuccess |
if the fallback method in the HystrixInvokable completes successfully |
onCacheHit |
if the response to the HystrixInvokable is found in the HystrixRequestCache
|
When you invoke a HystrixCommand
for the first time, it begins to access functionality that is governed by plugins. Since you cannot swap out plugins at runtime, the plugins that the HystrixCommand
uses during this first invocation become the plugins that the HystrixCommand
will use for the duration of the JVM run.
If you registered a plugin in Archaius, then that plugin implementation is used. If not, then Hystrix chooses a default plugin. Here’s an example of how to use Archaius for this purpose: https://github.com/eirslett/pull-request-illustration.
If you wish to register a plugin before you invoke the HystrixCommand
for the first time, you may do so with code like the following:
HystrixPlugins.getInstance().registerEventNotifier(ACustomHystrixEventNotifierDefaultStrategy.getInstance());
Each of the plugins shown above exposes the base as an abstract class to be extended rather than as an interface to be implemented.
This is for 2 reasons:
You only need to override those methods that you need to customize. You can retain the default behavior of other methods by not altering them.
Each method implementation is intended to be stand-alone and not have side effects or state so when you override one method without changing another this should not have implications.
Extension is accomplished via abstract base classes primarily for the next reason...
As Hystrix evolves, each of these plugins may gain new methods as new functionality is added or new things are found that need to be customized by users.
If Hystrix used an interface for this purpose, it would either require a new interface each time new functionality was added (basically an interface per method) or it would necessitate breaking changes for anybody who has implemented the interface. This problem will go away in Java 8 when “default methods” will exist on interfaces, but it will be a while before that is available and this library can choose Java 8 as the minimum supported JDK version.
Hystrix uses abstract base classes so that new optional methods can be added in point releases instead of major releases without breaking existing implementations.
A Netflix Original Production
Tech Blog | Twitter @NetflixOSS | Twitter @HystrixOSS | Jobs