Defend Your Application with Netflix Hystrix

With micro-services architecture, we can build flexible and independently deployable software modules or systems that communicate with each other with the light mechanism like HTTP resource API and provide the result. It has many advantages over the monolithic applications as many applications are moving to cloud. Martin and James have written a very good article 'Microservices' on their site, which I think you guys will enjoy reading.

As a characteristic of enterprise distributed application, there can be services call on multiple layers in micro-service architecture. The diagram below in the Analysis section would help you to have more idea.

I've created a simple example to orchestrate the microservice architecture which you can find at GitHub.

Analysis

Now, here what if one or many services go down because of network failure or timeout issues or exception is thrown in that particular service? Since there is service call on multiple layers, it is common on a distributed system that a remote service may fail. Such failure may cascade to layers ultimately reaching to the user.

In order to handle such failure gracefully, we need to have a mechanism that falls back to some other service call or default service so that the cascading of the error stops and the user doesn't need to experience system failure. The situation can be as depicted below: (Source: Spring Cloud Netflix)

Figure: Preventing error cascading with fallback

Now, as a developer, we don't need to worry much about the creating fallback because we have got Netflix Hystrix. Thanks to Netflix for developing such a powerful and wonderful library for fault tolerance.

Netflix’s Hystrix library implements the Circuit Breaker design pattern which means that if a method call fails and that failures build up to a threshold, Hystrix opens the circuit so that subsequent calls automatically fail. While the circuit is open, Hystrix redirects call to the method, and they’re passed on to our specified fallback method.

Implementation

In order to clarify my understanding, I've created an example which you can find in my Gitbub repository.

I'm going to use the MovieAPI as my remote service which I mentioned in my earlier article 'Make Your App Resourceful with HATEOAS'.

I've used Feign as rest client in my example. So, to enable circuit-breaker pattern with Hystrix, you just need to add dependency and an annotation in your Spring Boot application.

build.gradle

   compile('org.springframework.cloud:spring-cloud-starter-hystrix')

ClientAppApplication.java

@EnableFeignClients(basePackages = {"com.eprogrammerz.examples"})
@EnableCircuitBreaker
@SpringBootApplication
public class ClientAppApplication {
   public static void main(String[] args) {
      SpringApplication.run(ClientAppApplication.class, args);
   }
}

Now, the Feign Rest client is:

@FeignClient(name = "movie-api", fallback = MovieApiFallback.class)
public interface MovieApi {
    @RequestMapping(method = RequestMethod.GET, value = "/movies/{id}")
    Movie getMovie(@PathVariable("id") Long id);
}

Here, I've mentioned fallback class as MovieApiFallback.class which is as follows:

@Component
public class MovieApiFallback implements MovieApi {
    @Override
    public Movie getMovie(@PathVariable("id") Long id) {
        return new Movie("Avatar", "James Camerson", "8/10");
    }
}

Whenever a remote call to /movies/{id} fails, fallback method ( which is of the same name and has same params as well as return type as in interface) will be called and the static response is returned.

To make the example more complete, I want to include service and controller layer too.

MovieService.java

@Service
public class MovieService {

    @Autowired
    MovieApi movieApi;

    public Movie findMovie(Long id){
        Movie movieOfTheDay = movieApi.getMovie(id);
        return movieOfTheDay;
    }
}

MovieController.java

@RestController
@Slf4j
public class RequestController {
    @Autowiredprivate MovieService movieService;

    @RequestMapping("/recommended")
    public ResponseEntity<Movie> getRecommendedMovie(){
        long movieOfTheDayId = getLuckyMovieId();
        log.info("Calling MovieService:findMovie({})", movieOfTheDayId);
        Movie movieRecommended = movieService.findMovie(movieOfTheDayId);
        return new ResponseEntity<>(movieRecommended, HttpStatus.OK);
    }

    /**
     * Helper method to provide the random long number
     * @return long number between 1200 and 1
     */
    private long getLuckyMovieId(){
        long id = (int)(new Random().nextDouble() * 4) + 1200;
        return id;
    }
}

Running apps

Run both 'movie-api' and 'client-app' and you will get the different response at different call on 'client-app'. One particular response to call

http://localhost:8082/recommended

is

{
  "name": "In Search of Lost Time",
  "directorName": "Marcel Proust",
  "rating": "3.5/5"
}

Now, let's simulate the remote call failure by stopping the 'movie-api'. Then also you'll get a response, but this time from fallback as:

{
  "name": "Avatar",
  "directorName": "James Camerson",
  "rating": "8/10"
}

Conclusion

There is a lot more than I wanted to mention about my working experience on application reliability with Hystrix library, which I want to continue in my later articles.

But the to take away point is that Netflix Hystrix provides the easiest way to prevent the application from failing with just some annotations. Isn't it cool???

Preventing Mutation on Cached Object: EhCache
Make your REST API resourceful with HATEOAS