hystrix usage example

Three degradation strategies of hystrix are:

  • Fuse triggered degradation
  • Timeout triggered degradation
  • Resource isolation triggers degradation, which is divided into thread pool and semaphore

The following are introduced in combination with examples.

1, Fuse triggered degradation

1. When the failure rate of a service reaches a certain limit, the fuse will be turned on. When the service is called later, it will be directly refused to execute fallback logic (the callee's service has a problem, and the caller will blow the fuse)
2. Two conditions for fuse opening

  1. The number of requests reaches the set threshold
  2. Request error proportion reaches the set threshold

3. Example

    /**
     * HystrixProperty Refer to hystrixCommandProperties for parameters
     * Degraded trigger fuse
     * @return
     * 10s When more than 5 requests are initiated and the failure rate exceeds 50%, the fuse is automatically turned on,
     * Requests from fuse opening to subsequent 5s will not enter the method, and
     * And directly trigger fallback, which is returned by the callback method.
     */
    @GetMapping("/circuitBreaker/{num}")
    @HystrixCommand(commandProperties  = {
            //Turn on fuse function
            @HystrixProperty (name = "circuitBreaker.enabled" ,value = "true"),
            //Set minimum number of requests
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value ="5"),
            //Fusing time: 5 seconds
            @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds" , value ="5000"), 
            //Wrong process proportion
             @HystrixProperty(name="circuitBreaker.errorThresholdPercentage",value = "50") 

    } ,fallbackMethod = "fallback")
    public String circuitBreaker(@PathVariable("num")int num){
        if(num%2==0){
            return "Normal access";
        }

        throw new RuntimeException("");
    }
    //The method of entering the participation request must be consistent
    public String fallback(int num){
        return "Fuse triggered degradation";
    }

Turn on the fuse switch

@SpringBootApplication
@EnableCircuitBreaker
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class,args);
    }

}

In this example, when the number of requests exceeds 5, that is, the sixth time, if the error rate exceeds 50%, the fuse will be opened and enter the fallback logic, and the fuse will execute the fallback logic within 5s of opening.

2, Timeout triggered degradation

1. When the access time of a service exceeds the specified time, it can be considered that the service has failed and will not continue to wait, and then degraded and returned.

2. Example

    /**
     * Timeout triggers degradation
     * @return
     */
    @GetMapping("/timeOut")
    @HystrixCommand(commandProperties  = {
        //Start timeout triggers degradation
        @HystrixProperty(name = "execution.timeout.enabled" , value = "true"),
        //Degradation will be triggered after 1s
        @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds" , value = "1000"),
    } ,fallbackMethod = "fallback")
    public String timeOut() throws InterruptedException {
        Thread.sleep(3000) ;
        return "Normal access";

    }


    public String fallback(){
        return "Trigger degradation";
    }

3, Resource isolation triggers degradation

1. There are two kinds of resource isolation trigger degradation: thread pool and semaphore. hystrix uses thread pool by default

Let's look at the semaphore

Semaphores limit the number of concurrent requests. If they exceed the set value, degradation will be triggered. The semaphore is characterized by using the thread of the container (such as tomcat) to process requests, which does not involve the up and down switching of threads. Because there is no timeout mechanism, it is suitable for scenarios that do not rely on external services.

     public String fallback(){
        return "Trigger degradation";
    }

    @GetMapping("/semaphore")
    @HystrixCommand(
            commandProperties = {
                    //There are two isolation methods: semaphore and thread pool
                    @HystrixProperty(name = "execution.isolation.strategy" , value = "SEMAPHORE"),
                    //The semaphore size is 10 by default, and 500-1000 is recommended
                    //This means that this service cannot have more than two concurrent requests at the same time
                    @HystrixProperty(name = "execution.isolation.semaphore.maxConcurrentRequests" , value = "2") 
            },
            fallbackMethod = "fallback"
    )
    public String semaphore() throws InterruptedException {
        return "semaphore Normal access";
    }

Let's look at the way of offline process pool

hystrix abstracts the resources or services that need to be isolated into a command object, and then uses the set and independent thread pool to execute, so as not to affect other services.
A feature of thread pool isolation is that a new thread pool is created outside the threads of the container (such as tomcat), which requires additional maintenance of the thread pool, which will have a certain overhead (but the official test report says that the overhead is not large).

 private int num1 = 1;
   
@HystrixCommand(
            commandProperties = {
                    //Isolation using thread pool
                    @HystrixProperty(name = "execution.isolation.strategy" , value = "THREAD"),  
                    //The timeout is set to 3 seconds
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds" , value = "3000"),  

            },
            threadPoolProperties = {
                    //Thread pool size
                    @HystrixProperty(name = "coreSize" , value = "20"), 
                    //Waiting queue length
                    @HystrixProperty(name = "maxQueueSize" , value = "1000"),     
                    //Thread lifetime
                    @HystrixProperty(name = "keepAliveTimeMinutes", value = "2"),
                    /**
                     * Even if maxQueueSize is not reached, it is reached
                     * queueSizeRejectionThreshold After this value,
                     * The request will also be rejected. Because maxQueueSize cannot be dynamically modified,
                     * This parameter will allow us to set this value dynamically
                     */
                    @HystrixProperty(name = "queueSizeRejectionThreshold" , value = "800"),  
            },
            groupKey = "ThreadService", commandKey = "thread" ,threadPoolKey = "ThreadService",
            fallbackMethod = "fallback"
            )
    public void  thread() throws  Exception  {
        Thread.sleep(1000);
        System.out.println(Thread.currentThread() + "Normal access" + num1++);
    }



    public void fallback(){
        System.out.println("Fusing time:" + new Date());
    }

It should be noted that the "timeout" is timeoutInMilliseconds. In the example, 3s is set. When using, it may fuse only at 4s. This is related to thread startup, and the time will be slightly different.

Keywords: Java Hystrix

Added by MajusC00L on Sat, 12 Feb 2022 06:40:46 +0200