Overview
In this article, we'll introduce you to Spring Cloud Netflix Turbine. It aggregates multiple Hystrix Metrics Streams into one, so that it could be displayed into a single dashboard view.
To give a small introduction to Hystrix. In a microservice architecture, we have many small applications that talk to each other to complete a request.
There is always a possibility that one of these downstream services won't respond correctly or simply fails completely. To prevent any cascading failures we set up a Hystrix fallback mechanism for our microservices.
Each microservice that implements Hystrix can choose to expose the Hystrix Metrics Streams (via the actuator endpoint /hystrix.stream
) that can be viewed via the Hystrix Dashboard.
We've covered this in detail in Spring Cloud: Hystrix if you want to learn more.
Turbine is an open-source tool from Netflix for aggregating multiple streams into a single stream. Spring provided a nice wrapper around it to be easily used in the Spring ecosystem.
Setup
The setup is similar to the Spring Cloud: Hystrix setup. Here's what our back-end service looks like:
- Eureka Server: Acts as a service registry and runs on port
8761
. - Recommendation Service: A simple REST service that has a single endpoint of
/recommendations
and runs on port8070
. - User Service: A simple REST service that has a single endpoint of
/personalized/{id}
and runs on port8060
. - Hystrix Turbine: A Hystrix dashboard service to display Hystrix streams running on port
9090
.
Here is what our services look like on the Eureka server:
Both the user-service
and recommendation-service
have implemented the Hystrix fallback mechanism and have the /hystrix.stream
endpoint exposed via Actuator:
- Hystrix endpoint for user-service:
http://localhost:8060/actuator/hystrix.stream
- Hystrix endpoint for recommendation-service:
http://localhost:8070/actuator/hystrix.stream
We can check both this individually in our Hystrix Dashboard by typing the URL in the box and clicking "Monitor Stream":
We'll see a metric like this:
Note: If you don't see any stream, then you probably have to hit the endpoints of the service whose stream you want to see. Ex: foruser-service
we have to hit http://localhost:8060/personalized/1
to generate the stream.
Installing Turbine
You might have realized that looking at the individual stream is not very productive, especially when we have many microservices.
Turbine can aggregate all these individual hystrix.stream
s to a single turbine.stream
, which can be viewed on the Hystrix Dashboard.
It uses the DiscoveryClient
interface to find out relevant services that produce /hystrix.stream
s.
To add Turbine to your Hystrix Dashboard, add the following dependency:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-turbine</artifactId>
</dependency>
Check out our hands-on, practical guide to learning Git, with best-practices, industry-accepted standards, and included cheat sheet. Stop Googling Git commands and actually learn it!
Note: This is a starter dependency of turbine, which by default uses Spring Cloud Eureka as the discovery server. If you are using Spring Cloud Consul, use the following dependencies:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-turbine</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
In this article we'll be using the starter dependency, i.e spring-cloud-starter-netflix-turbine
.
To enable Turbine, we simply annotate our main class with @EnableTurbine
:
@SpringBootApplication
@EnableTurbine
@EnableDiscoveryClient
@EnableHystrixDashboard
public class HystrixTurbineApplication {
public static void main(String[] args) {
SpringApplication.run(HystrixTurbineApplication.class, args);
}
}
For Turbine to work as expected we have to add few details to our application.properties
:
server.port= 9090
spring.application.name= hystrix-turbine
eureka.client.serviceUrl.defaultZone= http://localhost:8761/eureka/
turbine.appConfig= user-service,recommendation-service
turbine.clusterNameExpression= new String("default")
Here, we are telling Turbine the Eureka server location, applications whose /hystrix.stream
it needs to fetch and turbine.clusterNameExpression
as new String("default")
, which gives the cluster name of "default".
We can open up http://localhost:9090/turbine.stream?cluster=default
to see the aggregate stream of both user-service
and recommendation-service
:
Again, if you are not viewing anything, just hit the user-service
and recommendation-service
endpoints to generate the streams.
We can also use this URL on our Hystrix dashboard to generate a nice aggregated view:
Sometimes, you may want to use Eureka's serviceId
s as cluster names for your dashboard. This can be done by using turbine.aggregator.clusterConfig
:
server.port= 9090
spring.application.name= hystrix-turbine
eureka.client.serviceUrl.defaultZone= http://localhost:8761/eureka/
turbine.aggregator.clusterConfig= USER-SERVICE,RECOMMENDATION-SERVICE
turbine.appConfig= user-service,recommendation-service
You can also check what clusters are currently configured in your Turbine application by hitting the /clusters
endpoint.
This endpoint can be disabled by setting turbine.endpoints.clusters.enabled
to false
.
So, now we can view turbine.stream
as Eureka IDs such as: http://localhost:9090/turbine.stream?cluster=USER-SERVICE
If there are multiple instances of a particular service running, Turbine will pick it up as per cluster and display it in the result.
Conclusion
In this article, we've covered how to set up the Turbine on top of our Hystrix stream for an aggregated view. We first saw the classical Turbine approach of fetching Hystrix stream from all services.
As always, the code for the examples used in this article can be found on GitHub.