Circuit breaker and monitoring

In general terms, a circuit breaker is:

An automatic device for stopping the flow of current in an electric circuit as a safety measure.

The same concept is used for microservice development, known as the Circuit Breaker design pattern. It tracks the availability of external services such as Eureka Server, API services such as restaurant-service, and so on, and prevents service consumers from performing any action on any service that is not available.

It is another important aspect of microservice architecture, a safety measure (failsafe mechanism) when the service does not respond to a call made by the service consumer – circuit breaker.

We'll use Netflix Hystrix as a circuit breaker. It calls the internal fallback method in the service consumer when failures occur (for example due to a communication error or timeout). It executes embedded within its consumer of service. In the next section, you will find the code that implements this feature.

Hystrix opens the circuit and fail-fast when the service fails to respond repeatedly, until the service is available again. You must be wondering, if Hystrix opens the circuit, then how does it know that the service is available? It exceptionally allows some requests to call the service.

Using Hystrix's fallback methods

There are three steps for implementing fallback methods:

  1. Enable the circuit breaker: The main class of microservice that consumes other services should be annotated with @EnableCircuitBreaker. For example, if a user service would like to get the restaurant details, where a user has reserved the table:
    @SpringBootApplication
    @EnableCircuitBreaker
    @ComponentScan({"com.packtpub.mmj.user.service", "com.packtpub.mmj.common"})
    public class UsersApp {
  2. Configure the fallback method: To configure the fallbackMethod, the @HystrixCommand annotation is used:
    @HystrixCommand(fallbackMethod = "defaultRestaurant")
    public ResponseEntity<Restaurant> getRestaurantById(int restaurantId) {
    
        LOG.debug("Get Restaurant By Id with Hystrix protection");
    
        URI uri = util.getServiceUrl("restaurant-service");
    
        String url = uri.toString() + "/v1/restaurants/" + restaurantId;
        LOG.debug("Get Restaurant By Id URL: {}", url);
    
        ResponseEntity<Restaurant> response = restTemplate.getForEntity(url, Restaurant.class);
        LOG.debug("Get Restaurant By Id http-status: {}", response.getStatusCode());
        LOG.debug("GET Restaurant body: {}", response.getBody());
    
        Restaurant restaurant = response.getBody();
        LOG.debug("Restaurant ID: {}", restaurant.getId());
    
        return serviceHelper.createOkResponse(restaurant);
    }
  3. Define fallback method: A method that handles the failure and performs the steps for safety:
    public ResponseEntity<Restaurant> defaultRestaurant(int restaurantId) {
        LOG.warn("Fallback method for restaurant-service is being used.");
        return serviceHelper.createResponse(null, HttpStatus.BAD_GATEWAY);
    }

These steps should be enough to failsafe the service calls and return a more appropriate response to the service consumer.

Monitoring

Hystrix provides the dashboard with a web UI that provides nice graphics of circuit breakers:

Monitoring

Default Hystrix dashboard

Netflix Turbine is a web application that connects to the instances of your Hystrix applications in a cluster and aggregates information, which it does in real time (updated every 0.5 seconds). Turbine provides information using a stream that is known as a turbine stream.

If you combine Hystrix with Netflix Turbine, then you can get all the information from Eureka Server on the Hystrix dashboard. This gives you a landscape view of all the information about the circuit breakers.

To use Turbine with Hystrix, just type in the Turbine URL http://localhost:8989/turbine.stream (port 8989 is configured for the Turbine server in application.yml) in first textbox shown before, and click on Monitory Stream.

Netflix Hystrix and Turbine uses RabbitMQ, an open source message queuing software. RabbitMQ works on Advance Messaging Queue Protocol (AMQP). It is a software in which queues can be defined, where applications can establish a connection and transfer a message through it. A message can include any kind of information. A message can be stored in the RabbitMQ queue until a receiver application connects and receives the message (taking the message off the queue).

Hystrix uses RabbitMQ to send a metrics data feed to Turbine.

Note

Before we configure Hystrix and Turbine, please install the RabbitMQ application on your platform. Hystrix and Turbine use RabbitMQ to communicate between themselves.

Setting up the Hystrix Dashboard

We'll add the new Maven dependency, dashboard-server for Hystrix Server. Configuring and using the Hystrix Dashboard is pretty simple in Spring Cloud like others. You just need to follow these steps:

  1. Define the Hystrix Dashboard dependency in pom.xml:
    <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter- hystrix-dashboard</artifactId>
    </dependency>
  2. The @EnableHystrixDashboard annotation in the main Java class does everything for you to use it. We'll also use the @Controller to forward the request from the root to Hystrix, as shown here:
    @SpringBootApplication
    @Controller
    @EnableHystrixDashboard
    public class DashboardApp extends SpringBootServletInitializer {
    
        @RequestMapping("/")
        public String home() {
            return "forward:/hystrix";
        }
    
        @Override
        protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
            return application.sources(DashboardApp.class).web(true);
        }
    
        public static void main(String[] args) {
            SpringApplication.run(DashboardApp.class, args);
        }
    }
  3. Update the Dashboard application configuration in application.yml, as shown here:
    application.yml
    # Hystrix Dashboard properties
    spring:
        application:
            name: dashboard-server
    
    endpoints:
        restart:
            enabled: true
        shutdown:
            enabled: true
    
    server:
        port: 7979
    
    eureka:
        instance:
            leaseRenewalIntervalInSeconds: 3
            metadataMap:
                instanceId: ${vcap.application.instance_id:${spring.application.name}:${spring.application.instance_id:${random.value}}}
    
        client:
            # Default values comes from org.springframework.cloud.netflix.eurek.EurekaClientConfigBean
            registryFetchIntervalSeconds: 5
            instanceInfoReplicationIntervalSeconds: 5
            initialInstanceInfoReplicationIntervalSeconds: 5
            serviceUrl:
                defaultZone: http://localhost:8761/eureka/
            fetchRegistry: false
    
    logging:
        level:
            ROOT: WARN
            org.springframework.web: WARN

Setting up Turbine

We'll create one more Maven dependency for Turbine. When you run the Hystrix Dashboard application, it will look like the Default Hystrix Dashboard screenshot shown earlier.

Now, we will configure the Turbine Server using the following steps:

  1. Define the Turbine Server dependency in pom.xml:
    <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-turbine-amqp</artifactId>
    </dependency>
  2. Use the @EnableTurbineAmqp annotation in your application class as shown here. We are also defining a bean that will return the RabbitMQ Connection Factory:
    @SpringBootApplication
    @EnableTurbineAmqp
    @EnableDiscoveryClient
    public class TurbineApp {
    
        private static final Logger LOG = LoggerFactory.getLogger(TurbineApp.class);
    
        @Value("${app.rabbitmq.host:localhost}")
        String rabbitMQHost;
    
        @Bean
        public ConnectionFactory connectionFactory() {
            LOG.info("Creating RabbitMQHost ConnectionFactory for host: {}", rabbitMQHost);
            CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory(rabbitMQHost);
            return cachingConnectionFactory;
        }
    
        public static void main(String[] args) {
            SpringApplication.run(TurbineApp.class, args);
        }
    }
  3. Update the Turbine configuration in application.yml, as shown here:

    server:port: The main port used by the the turbine HTTP

    management:port: Port of turbine Actuator endpoints

    application.yml
    spring:
        application:
            name: turbine-server
    
    server:
        port: 8989
    
    management:
        port: 8990
    
    PREFIX:
    
    endpoints:
        restart:
            enabled: true
        shutdown:
            enabled: true
    
    eureka:
        instance:
            leaseRenewalIntervalInSeconds: 10
        client:
            registryFetchIntervalSeconds: 5
            instanceInfoReplicationIntervalSeconds: 5
            initialInstanceInfoReplicationIntervalSeconds: 5
            serviceUrl:
                defaultZone: http://localhost:8761/eureka/
    
    logging:
        level:
            root: WARN
            com.netflix.discovery: 'OFF'

    Note

    Please be aware the preceding steps always create the respective servers with default configurations. If required, you can override the default configuration with specific settings.

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

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