Spring Cloud: Turbine

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 running on port 8761.
  • Recommendation Service: A simple REST service that has a single endpoint of /recommendations and running on port 8070.
  • User Service: A simple REST service that has a single endpoint of /personalized/{id} and running on port 8060.
  • 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:

spring-cloud-turbine-setup

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 recommnedation-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":

spring-cloud-turbine-dashboard

We'll see a metric like this:

spring-cloud-turbine-dashboard-single-stream

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.streams 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.streams.

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>  

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.propeties:

server.port= 9090  
spring.application.name= hystirx-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:

spring-cloud-turbine-stream

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:

spring-cloud-turbine-stream-in-dashboard

Sometimes, you may want to use Eureka's serviceIds as cluster names for your dashboard. This can be done by using turbine.aggregator.clusterConfig:

server.port= 9090  
spring.application.name= hystirx-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.

spring-cloud-turbine-cluster-endpoint

So, now we can view turbine.stream as Eureka IDs such as: http://localhost:9090/turbine.stream?cluster=USER-SERVICE

spring-cloud-turbine-service-id-cluster

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.