Open In App

Spring Cloud Netflix – Hystrix

Last Updated : 20 Feb, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

In Spring Boot, Spring Cloud Netflix can be used to build the microservices architecture with the help of various components. In Spring Cloud Netflix, Hystrix is one of the components, and it can be used to stop cascading failures and enable resilience in complex distributed systems. It is a latency and fault tolerance library designed to isolate points of access to remote systems.

Key Terminologies:

  • Circuit Breaker: In Spring Cloud Netflix, Hystrix can use the circuit breaker pattern to stop cascading failures in the microservices environment. When failures occur, the circuit breaker calling the failing services is automatically redirected to the fallback mechanism.
  • Fallback: The fallback Mechanism can be used to execute a call when a service call fails, and it provides the graceful degradation of the service.
  • Command: Hystrix command can be used to represent a potential failure point in the system or microservice.
  • Matrix: Matrix can be used to provide the monitoring and metrics to track the health and performance of the microservices.

Example Project:

In our example, project we can implement the user register and login API along with the Hystrix fallback mechanism using Spring Cloud Netflix (Hystrix). Hystrix fallback mechanism can handle the failures of the register and login API’s.

  • Once the user registers, username and password details are stored in the MongoDB database.
  • If any errors occur and the API endpoint is down, then their a fallback response to the user.

Prerequisites:

  • Advance Java Programming
  • Spring Framework
  • Basic understanding MongoDB

Workflow diagram:

fallback_mechanism-(1)

Project Requirements:

Create the project with the below configuration:

  • Project: Maven
  • Language: Java
  • Packaging: Jar
  • Java version: 17

Project Structure:

Project Structure

Step-by-Step Implementation of Hystrix in Spring Cloud Netflix

Step 1: Create the Spring project with the below mentioned dependencies and open the project into the Spring STS IDE (recommended).

While creating the project, add the following dependencies.

  • Spring Web
  • Spring Data MongoDB
  • Spring Web Security
  • Lombok
  • Spring Cloud Netflix Hystrix

Note: You are unable to find the Netflix hystrix into the spring dependence’s, so, we will provide the code below you can paste it into you pom.xml file.

Open the application.properties file then configure the mongodb database and netflix hystrix mechanism into your spring project. Put the code in the application.properties file.

Go to the src > main > java > resource > Application and put the below code.

server.port=8082
spring.data.mongodb.uri=mongodb://localhost:27017/users

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 5000

Step 2: Once successful create the project after that create the one package named as the model in that package create one class named as User.

Go to the src > main > java > model and create a User class and put the below code.

Java




package in.mahesh.tasks.model;
  
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
  
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
  
@Document
@AllArgsConstructor
@NoArgsConstructor
public class User {
      
    @Id
    private String id;
    private String email;
    private String password;
      
    public String getId() {
          
        return id;
    }
    public void setId(String id) {
          
        this.id = id;
    }
    public String getEmail() {
          
        return email;
    }
    public void setEmail(String email) {
          
        this.email = email;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
      
      
  
}


Create one more class in same package and it named as the LoginRequest and this class handle login request into the project.

Java




package in.mahesh.tasks.model;
  
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
  
@Data
@AllArgsConstructor
@NoArgsConstructor
public class LoginRequest {
      
    String email;
    String password;
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
      
      
  
}


Step 3: Now, we can create one more package and it named as repository in that repository create an interface named as UserRepository and put the code below.

Go to the src > main > java > repository > UserRepository

Java




package in.mahesh.tasks.repository;
  
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.Query;
import org.springframework.stereotype.Repository;
  
import in.mahesh.tasks.model.User;
  
@Repository
public interface UserRepository extends MongoRepository<User, String> {
  
    @Query("{email :?0}")
    User findByEmail(String username);
  
}


Step 4: Create one more package and it named as the controller after that create the class in that package and it named as the UserController and this class can handles the requests from the user.

Note: Add the EnableHystrix annotation into the UserController class to enabling the hystrix fallback mechanism in this project.

Go to the src > main > java > controller> UserController and put the code below:

Java




package in.mahesh.tasks.controller;
  
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
  
import in.mahesh.tasks.model.LoginRequest;
import in.mahesh.tasks.model.User;
import in.mahesh.tasks.repository.UserRepository;
import org.springframework.web.client.RestTemplate;
  
@RestController
@EnableHystrix
public class UserController {
      
      
      @Autowired 
      UserRepository userRepository;
        
      @Autowired
      PasswordEncoder passwordEncoder;
        
      @PostMapping("/signup"
     @HystrixCommand(fallbackMethod = "fallbackRegisterUser")
      public ResponseEntity<String> createUserHandler(@RequestBody User user) { 
      String email = user.getEmail();
      String password = user.getPassword(); 
      User createdUser = new User();
      createdUser.setEmail(email); 
      createdUser.setPassword(passwordEncoder.encode(password));
        
      User savedUser = userRepository.save(createdUser);
      userRepository.save(savedUser); return new
      ResponseEntity<>("User Registration Sucess", HttpStatus.OK);
        
      }
       
      
      @PostMapping("/signin"
     @HystrixCommand(fallbackMethod = "fallbackLoginUser")
      public ResponseEntity<String> sign(@RequestBody LoginRequest loginRequest) {
      String username = loginRequest.getEmail(); 
      String password = loginRequest.getPassword();
        
      // Retrieve the user from the database based on the email
      User user = userRepository.findByEmail(username);
  
      if (user == null) {
          return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
                  .body("Invalid email or password");
      }
  
      // Verify the password
      if (!passwordEncoder.matches(password, user.getPassword())) {
          return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
                  .body("Invalid email or password");
      }
  
      // You can generate a token here and return it as part of the response
      // For simplicity, let's just return a success message for now
      return ResponseEntity.ok("Login successful");
  
        
 }
  
      // Fallback method for user registration
  
 public ResponseEntity<String> fallbackRegisterUser(User user) {
          // Lothe error or perform any necessary handling
      System.err.println("User registration failed. Fallback method called.");
      return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
      .body("User Registration Failed. Please try again later."); }
  
     // Fallback method for user login
  
       public ResponseEntity<String> fallbackLoginUser(LoginRequest
      loginRequest) { // Log the error or perform any necessary handling
      System.err.println("User login failed. Fallback method called."); return
      ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
      .body("User Login Failed. Please try again later."); }
  
  
}


Step 5: In main package, create the one more class and it named as the AppConfig and this class can be configure the web security of the project.

Go to the src > main > java > AppConfig and put the code below:

Java




package in.mahesh.tasks;
  
import java.util.Arrays;
import java.util.Collections;
  
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
  
  
@Configuration
@EnableWebSecurity
public class AppConfig {
    @SuppressWarnings("deprecation")
    @Bean
    SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.sessionManagement(management -> management.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .authorizeRequests(
                        authorize -> authorize.requestMatchers("/api/**")
                        .authenticated().anyRequest().permitAll())
                .csrf(csrf -> csrf.disable())
                .httpBasic(Customizer.withDefaults())
                .formLogin(Customizer.withDefaults());
                  return http.build();
    }
  
  
  
    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
  
}


Step 6: In main package, by default the main class created by the creation of the bring project in this class we can enable the Hystrix to be working with the Netflix Hystrix into the spring project.

Go to the src > main > java > UserServiceApplication and put the code below:

Java




package in.mahesh.tasks;
  
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
  
@SpringBootApplication
@EnableHystrix
public class UserServiceApplication {
  
    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
    }
  
}


Step 7: Once successfully completed the project then run the project as a spring application once the successfully then we will the output like the below image. In our case application start on port 8082.

Console Output

Once the application is successfully, open the Postman tool and check if the endpoints and fallback methods are working properly or not.

Register Endpoint:

http://localpoint:8082/signup

Reference the below image for better understanding:

Hystrix Register

Check the login endpoint:

http://localpoint:8082/signin

Reference the below image for better understanding:

Hystrix login

Fallback Mechanism:

Below we can see the fallback login details and output in the request body.

Fallback Login

Now we can check if the Hystrix fallback will work or not. In our case, we can register the same details multiple times. Now that we can try to login with the same login details. We raise the fallback method because if we enter the same details multiple times, the login request is unable to find the details, so, the fallback method is raised.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads