Netflix OSS: A beginner's guide [pt4]
When a system grows, you need some kind of monitoring as well. If you have a monolithic app, that is not really a hard task, but when it comes to microservices word, things change.
How to keep track of hundreds of instances? How do you know if one of them fails?
Netflix solve this issue with Hystrix and Turbine.
Hystrix
Hystrix is a library designed " to control the interactions between distributed services providing greater tolerance of latency and failure". In short, Hystrix can wrap API calls ensuring that if something goes wrong, you will 1) know about right away and 2) provide a fallback method in order to prevent cascading failure. It does it through Circuit breaker
Turbine
But how do you aggregate all Hystrix endpoints from hundreds of services? Thats a job for Turbine. Hystrix provide information through Server-Sent Event (SSE) JSON data and Turbine can aggregate them.
Putting them to work
So far we have Eureka as service discovery backend, Zuul proxying our API calls and one instance of contacts-service
, where the game happens.
Now, we want to monitor calls to our service and not care if there are 1 or 1000 instance of it.
in contact's pom.xml
lets add the Hystrix dependice with
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
and in the main class, annotate with @EnableCircuitBreaker
.
To wrap a function with circuit breaker, you should provide a fallback function. In our component responsible for load the contacts, lets do the following:
@HystrixCommand(fallbackMethod="getUsersFallback")
public Iterable<Contact> getContacts() throws IOException{
return repository.findAll();
}
public Iterable<Contact> getUsersFallback(){
return new ArrayList<>();
}
the @HystrixCommand
annotation demands a value for fallbackMethod
option. This method should accept the same params as the original function, in types and numbers.
You also need to add Spring Boot Actuator as dependency to the app in order to expose the Hystrix endpoint.
Hystrix Dashboard
We will have one single app for all: the dashboard and the aggregator. To do so, lets got to start.spring.io and create a new app as follows:
Download the project and annotate its main class with
@EnableHystrixDashboard
@EnableTurbine
@EnableEurekaClient
The first two annotations are self explanatory and the last one is needed because Turbine will connect to Eureka, ping all services available, searching for any Hystrix endpoint.
Here is the configuration for Eureka and Turbine:
server.port: 8090
eureka:
client:
serviceUrl:
defaultZone: http://127.0.0.1:8761/eureka/
instance:
preferIpAddress: false
turbine:
aggregator:
clusterConfig: CONTACTS-SERVICE
appConfig: CONTACTS-SERVICE
The first section we know from past blog posts: connecting to Eureka. The second is new. We are telling Turbine what and how to aggregate our Hystrix endpoints. clusterConfig
is the name of the cluster, it is how we are going to access it and appConfig
is the name of the service we want to aggregate. We can have multiple services aggregated in the same Turbine app with, for example, appConfig: customers,stores,ui,admin
Now, lets deploy everything. and access the the Hystrix Dashboard on 8090
:
in the field available, point it to Turbine stream endpoint. You will be redirected to the dashboard. Do some calls to the contacts endpoints and you will see something like this
The dashboards shows that our method getContacts
is working fine (as the circuit is closed) and we have one host in the aggregator. If you deploy more instances you will see the Hosts
number increasing. Here I deployed one more and the numbers changed:
And thats it, using Hystrix you can have a basic monitoring deployed in a couple of hours that works independently from the number of hosts you have and in real time.