How it works...

In this recipe we have done three things after adding the Hystrix dependency library to our project. So, let's take a look at each step in detail to learn what exactly happens:

  • The @EnableCircuitBreaker annotation, similar to @EnableDiscoveryClient, or @EnableFeignClients, which explicitly indicates that we want Spring Cloud to load appropriate configurations from spring.factories from all the libraries which have the org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker key defined.
  • In the case of Hystrix, it will load HystrixCircuitBreakerConfiguration, which provides the necessary configuration to enable the Hystrix functionality within the application. One of the beans it creates, is the HystrixCommandAspect class. It's purpose is to detect all the methods which are annotated with the @HystrixCommand annotation and wrap them with a handler to detect errors, timeouts, and other ill-behaviors, and deal with them appropriately, based on configuration.
  • This @HystrixCommand annotation, provided by the Hystrix library, is designed to mark methods which represent Hystrix-guarded commands, that is, methods which we want to protect using Hystrix against cascading failures and overloads. This annotation has a number of attributes and can be configured in a variety of different ways, depending on the desired behavior.
  • In our example we have used the most typical attribute—fallbackMethod, which allows us to configure an alternative method, with matching signature, which can be automatically called if the real method fails the invocation for whatever reason. This is the prime use-case, and it provides the ability to specify graceful degradation of service, using sensible defaults, if possible, instead of blowing up exceptions up the stack.
  • We used it to direct failed calls to the getEmptyBooksList() method, which returns a static empty list. This way, when the real getAllBooks() method fails, we gracefully degrade and return an empty collection, which renders nicely as a response JSON. In the situations when we do indeed desire a particular type of exception to be propagated up the stack, we can configure those explicitly using the ignoreExceptions attribute and set it to the desired exception classes.
  • To configure the circuit breaker behavior of a particular command, we can set a number of different options using the commandProperties or threadPoolProperties attributes. There we can set things like execution timeouts, size of backup queues, and many others.

One last thing to discuss is the modifications we made to our entity models to set the relational association annotations to use fetch = FetchType.EAGER. The reason we had to do so is due to the way Hibernate handles association loading. By default, those are loaded using the FetchType.LAZY setup, meaning that Hibernate is only going to establish the relationship, but the loading of the data will not happen until the getter methods are invoked. With Hystrix, by default, this could cause an error that looks something like this:

failed to lazily initialize a collection of role: com.example.bookpub.entity.Book.reviewers, could not initialize proxy - no Session (through reference chain: com.example.bookpub.entity.Publisher["books"]->org.hibernate.collection.internal.PersistentBag[0]->com.example.bookpub.entity.Book["reviewers"])

This is due to the fact that Hystrix uses ThreadPool to execute method calls by default, and because the lazy-loaded data needs to access the datastore at the time of invocation, Hibernate requires an active session to be present in order to handle the request. Since Hibernate stores the session in ThreadLocal, it is obviously not present in the pooled executor thread that Hystrix is using during the invocation.

Once we changed the fetching to be eager, all the data is loaded during the repository interaction in the original Hibernate thread. We could, alternatively, configure our @HystrixCommand annotation to use the same executing thread by using the following configuration:

commandProperties = { 
  @HystrixProperty(name="execution.isolation.strategy", 
                   value="SEMAPHORE") 
} 

While Hystrix strongly recommends to use the default THREAD strategy, in situations when we absolutely need to be residing in the same caller thread, SEMAPHORE is there to help us.

Alternatively, we can set the same configuration in our application.properties file using hystrix.command.default.execution.isolation.strategy=SEMAPHORE, or, if we want to be specific to only configure particular @HystrixCommand, we can use the value of the commandKey attribute, which is the name of the annotated method by default, instead of the default section of the property name. For our specific example from the BookController instrumented method, the configuration key would look like hystrix.command.getAllBooks.execution.isolation.strategy=SEMAPHORE. This is possible thanks to the Spring Cloud-Netflix Archaius bridge, which makes all Spring environment properties visible to the Archaius configuration manager, thus accessible by all of the Netflix components.

Spring Cloud Hystrix integration also provides a /hystrix.stream actuator endpoint, which can be consumed by the Hystrix dashboard for visualizing the state of all the circuit breakers in an application.

To get the dashboard running quickly, Spring Cloud provides a sample application which can be seen at https://github.com/spring-cloud-samples/hystrix-dashboard:

The same stream can also be fed into Netflix Turbine Stream Aggregator, downloadable at https://github.com/Netflix/Turbine, for data aggregation across multiple instances, which can later be visualized using the same dashboard.

One can also use the spring-cloud-starter-turbine dependency library and the @EnableTurbine annotation on a basic Spring Boot application, similar to the Hystrix dashboard sample.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.130.31