Spring cloud Netflix circuit breaker Hystrix

What is Hystrix

Hystrix is an open source library for dealing with delay and fault tolerance of distributed systems. In distributed systems, many dependencies inevitably fail to call, such as timeout and exception. Hystrix can ensure that in the case of a dependency failure, it will not lead to overall service failure, avoid cascading failures, and improve the elasticity of distributed systems.

"Circuit breaker" itself is a kind of switching device. When a service unit fails, it returns an expected and treatable alternative response (FallBack) to the caller through the fault monitoring of the circuit breaker (similar to a blown fuse), rather than waiting for a long time or throwing an exception that the caller cannot handle, This ensures that the thread of the service caller will not be occupied unnecessarily for a long time, so as to avoid the spread and even avalanche of faults in the distributed system.

Use of Hystrix

  1. pom introduces dependency
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
  1. The startup class is annotated with @ EnableHystrix or @ enablercircuitbreaker
@SpringBootApplication
@EnableDiscoveryClient
@EnableHystrix
@EnableFeignClients
public class EurekaConsumerApp {
    public static void main(String[] args) {
        new SpringApplicationBuilder(EurekaConsumerApp.class)
                .web(WebApplicationType.SERVLET).run(args);
    }
}

Service degradation and timeout

Degradation: a microservice takes too long to respond or is unavailable. It cannot return the error message or keep it stuck. Therefore, it is necessary to prepare a corresponding strategy. When this happens, call this strategy directly and return the request quickly.

  1. Add @ HystrixCommand annotation on the method and specify fallbackMethod degradation policy
  2. Provider simulation exception
@RestController
@RequestMapping("client")
public class IndexController {

    @Autowired
    RestTemplate restTemplate;

    @GetMapping
    @HystrixCommand(fallbackMethod = "selectFallback")
    public String select(String type){
        HashMap<String, String> map = new HashMap<>();
        map.put("type",type);
        return restTemplate.getForObject("http://EUREKA-PRODUCT/product?type={type}", String.class,map);
    }

    public String selectFallback(String type) {
        return "service degradation :" + type;
    }
}
@RestController
@RequestMapping("product")
public class UserController {

    private static String shareName = "init name";

    @Value("${server.port}")
    private String serverPort;

    @GetMapping
    public String select(String type) throws InterruptedException {
        if ("abnormal".equals(type)){
            throw new RuntimeException("Simulation anomaly");
        }
        if ("overtime".equals(type)){
            System.out.println("Timeout tests ");
           Thread.sleep(3000);
        }
        return serverPort + ":" + shareName;
    }
}

Timeout: Hystrix has a default timeout monitoring mechanism. When the request exceeds 1s, it will timeout, and timeout will also trigger degradation. Here, you can configure the timeout duration by configuring the class.

hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 1000 # Time out for degradation

Usage scenario: when the system cannot carry such a large amount of concurrency in the double 11 second kill or promotion activities, you can consider closing some unimportant microservices first (returning a more friendly information in the degradation method) and giving resources to the main microservices.

Fusing and current limiting

Fusing: fusing is like a fuse. When your circuit fails, hystrix will adopt a fusing mechanism to prohibit you from calling services. After disconnection, it will still be called occasionally to judge whether the service is restored

hystrix:
  command:
    default:
      circuitBreaker:
        requestVolumeThreshold: 10 # default 20 this attribute sets the minimum number of requests that will trigger the circuit in the scrolling window
      metrics:
        rollingStats:
          timeInMilliseconds: 10000 # When used in conjunction with requestvolumthreshold, 10 errors within 10s will open the circuit breaker

Current limit: limit the use of micro services. For example, limit the number of threads.

@GetMapping
@HystrixCommand(fallbackMethod = "selectFallback"  ,
                threadPoolKey = "order",
                threadPoolProperties ={@HystrixProperty(name = "coreSize",value = "2")
                                       ,@HystrixProperty(name = "maxQueueSize",value = "1")})
public String select(String type){
  HashMap<String, String> map = new HashMap<>();
  map.put("type",type);
  return restTemplate.getForObject("http://EUREKA-PRODUCT/product?type={type}",String.class,map);
}

threadPoolKey is the unique ID of the thread pool. hystrix will count your ID to see if the thread occupation exceeds. If it exceeds, it will directly degrade the call

For example, if the value given by coreSize here is 2, assuming that the method call time is 3s, if more than 2 requests come in within 3s, all the remaining requests will be degraded

What is the difference between fusing and degradation?

Feign integrates Hystrix

  1. application.yml configuration, open

    feign:
      hystrix:
        enabled: true
    
  2. Feign interface modification

    @FeignClient(name = "EUREKA-PRODUCT",fallbackFactory = UserClientFallBack.class,path = "/product")
    public interface UserClient {
        @GetMapping
        public String select(@RequestParam("type") String type);
    }
    
    @Component
    public class UserClientFallBack implements UserClient{
        @Override
        public String select(String type) {
            return "Service degradation: Feign hystrix";
        }
    }
    
  3. If you get the specific error information, modify it as follows

    @Component
    public class UserClientFallBackFactory implements FallbackFactory<UserClient> {
        @Override
        public UserClient create(Throwable throwable) {
            return new UserClient() {
                @Override
                public String select(String type) {
                    String message = throwable.getMessage();
                    System.err.println(message);
                    return "Service degradation: Feign hystrix"+message;
                }
            };
        }
    }
    
    @FeignClient(name = "EUREKA-PRODUCT",fallbackFactory = UserClientFallBackFactory.class,path = "/product")
    public interface UserClient {
        @GetMapping
        public String select(@RequestParam("type") String type);
    }
    

Keywords: Spring Cloud

Added by stephanie on Wed, 09 Feb 2022 17:53:49 +0200