Spring Cloud service circuit breaker and downgrade (Hystrix)

Table of Contents

Hystrix

concept

effect

Service downgrade

Introduction

scenes to be used

interface downgrade

Server service downgrade

1. Add dependencies

2. Define the interface

3. Implement the interface

4.Usage of Controller class

5. Add comments to the startup class

6. Browser access

Client service downgrade

1. Add dependencies

2. Add configuration in application.yml

3. Define the interface

4.Usage of Controller class

5. Add configuration in application.yml and configure the request timeout time on the client

6. Add comments to the startup class

7. Browser access

global downgrade

1. Annotation configuration

2.Creation method

3. Business method annotation annotation

4. Browser access

Service circuit breaker

Introduction

Fusing parameter settings

fuse type

fuse open

circuit breaker closed

fuse half open

circuit breaker

Steps for usage

Example

1. Define the interface

2. Implement the interface

3. Methods to provide external services

4. Browser access

Fault monitoring


In a microservices architecture, an application is often composed of multiple services. These services depend on each other and the dependencies are intricate.

When service E fails or the network is delayed, the following occurs:

1. Even if all other services are available, due to the unavailability of service E, user requests 1, 2, and 3 will be blocked, waiting for the response of service E. In high concurrency scenarios, the thread resources of the entire server will be quickly exhausted in a short period of time.

2. All other services that depend on service E, such as services B, D and F, will also be in a thread blocking state, waiting for the response of service E, resulting in the unavailability of these services.

3. All services that depend on services B, D and F, such as service A and service C, will also be in a thread blocking state, waiting for responses from service D and service F, causing service A and service C to also be unavailable.

When a service in the microservice system fails, the failure will spread crazily in the system along the service call link, eventually leading to the paralysis of the entire microservice system. This is the “avalanche effect”. In order to prevent such incidents from happening, the microservice architecture introduces a series of service fault tolerance and protection mechanisms called “circuit breakers”.

Hystrix

Concept

Hystrix is an open source library used to handle latency and fault tolerance in distributed systems. It can ensure that when a service fails, it will not cause an avalanche effect on the entire system to improve the resilience of the distributed system.

As a “circuit breaker”, when a service fails, it can be monitored through the short circuit breaker and a response result that can be processed is returned to ensure that the service calling thread will not be occupied for a long time and avoid the spread of faults.

role

Protect thread resources: Prevent the failure of a single service from depleting all thread resources in the system

Fast failure mechanism: When a service fails, the service caller will not be kept waiting, but will directly return the request failure.

Provide a downgrade (FallBack) plan: After the request fails, provide a designed downgrade plan, usually a fallback method, which is called when the request fails.

Prevent fault propagation: Use the circuit breaker mechanism to prevent faults from spreading to other services

Monitoring function: Provides Hystrix Dashboard, a fuse fault monitoring component, to monitor the status of fuses at any time

Service downgrade

Introduction

When a service failure occurs, the faulty service is downgraded to a pre-prepared failure processing result, and this result is returned to the service consumer;

like:

The client accesses service 1, service 1 calls service 2, service 2 fails, and the Hystrix service degrades, returning a processable result to service 1, and service 1 returns to the client with a friendly error interface.

Usage Scenario

1. When server pressure increases sharply, some unimportant and non-urgent services should be strategically not processed or simply processed based on actual business conditions and traffic, thereby releasing server resources to ensure the normal operation of core services.

2. When some services are unavailable, in order to avoid service lag or avalanche effect caused by long waiting, the backup downgrade logic is actively executed and a friendly prompt is returned immediately to ensure that the main business is not affected.

Interface downgrade

Server service downgrade
1. Add dependencies
<!--hystrix dependency-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
2. Define interface
public interface DeptService {

    // hystrix fuse example ok
    public String deptInfo_Ok(Integer id);

    //hystrix fuse timeout case
    public String deptInfo_Timeout(Integer id);
}
3. Implement the interface
@Service("deptService")
public class DeptServiceImpl implements DeptService {
    @Override
    public String deptInfo_Ok(Integer id) {
        return "Thread pool:" + Thread.currentThread().getName() + " deptInfo_Ok,id: " + id;
    }
    //Once the method fails and throws an exception message, the method specified by fallbackMethod annotated with @HystrixCommand will be automatically called.
    @HystrixCommand(fallbackMethod = "dept_TimeoutHandler",
            commandProperties=
                    //It is stipulated that no error will be reported within 5 seconds and the operation will be normal. If it exceeds 5 seconds, an error will be reported and the specified method will be called.
                    {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000")})
    @Override
    public String deptInfo_Timeout(Integer id) {
        int outTime = 6;
        try {
            TimeUnit.SECONDS.sleep(outTime);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "Thread pool:" + Thread.currentThread().getName() + " deptInfo_Timeout,id: " + id + " Time consuming: " + outTime;
    }
    //When the service fails, call this method to give a friendly prompt
    public String dept_TimeoutHandler(Integer id) {
       return "C Language Chinese website reminds you that the system is busy, please try again later!" + "Thread pool:" + Thread.currentThread().getName() + " deptInfo_Timeout,id: " + id;
    }
}

@HystrixCommand annotation:

The parameter fallbackMethod attribute is used to specify the fallback method

The parameter execution.isolation.thread.timeoutInMilliseconds is used to set the peak value of its own call timeout. It can run normally within the peak value, otherwise the downgrade method will be executed.

4.Controller class usage
@RestController
@Slf4j
public class DeptController {
    @Autowired
    private DeptService deptService;
    @Value("${server.port}")
    private String serverPort;
    @RequestMapping(value = "/dept/hystrix/ok/{id}")
    public String deptInfo_Ok(@PathVariable("id") Integer id) {
        String result = deptService.deptInfo_Ok(id);
        log.info("Port number:" + serverPort + " result:" + result);
        return result + ", port number: " + serverPort;
    }
    // Hystrix service timeout and downgrade
    @RequestMapping(value = "/dept/hystrix/timeout/{id}")
    public String deptInfo_Timeout(@PathVariable("id") Integer id) {
        String result = deptService.deptInfo_Timeout(id);
        log.info("Port number:" + serverPort + " result:" + result);
        return result + ", port number: " + serverPort;
    }
}
5. Add comments to startup class
@SpringBootApplication
@EnableEurekaClient //Enable Eureka client function
@EnableCircuitBreaker //Activate the fuse function
public class MicroServiceCloudProviderDeptHystrix8004Application {
    public static void main(String[] args) {
        SpringApplication.run(MicroServiceCloudProviderDeptHystrix8004Application.class, args);
    }
}
6. Browser access

Client service downgrade

Under normal circumstances, we will perform service downgrade on the client. When the service on the server called by the client is unavailable, the client directly performs service downgrade processing to avoid its thread being occupied for a long time and unnecessarily.

1. Add dependencies
<!--hystrix dependency-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
Add configuration in 2.application.yml

Add the following configuration to application.yml to enable the Hystrix function on the client

feign:
  hystrix:
    enabled: true #Enable client hystrix
3. Define interface
@Component
@FeignClient(value = "MICROSERVICECLOUDPROVIDERDEPTHYSTRIX")
public interface DeptHystrixService {
    @RequestMapping(value = "/dept/hystrix/ok/{id}")
    public String deptInfo_Ok(@PathVariable("id") Integer id);
    @RequestMapping(value = "/dept/hystrix/timeout/{id}")
    public String deptInfo_Timeout(@PathVariable("id") Integer id);
}
4.Controller class usage
@Slf4j
@RestController
public class HystrixController_Consumer {
    @Resource
    private DeptHystrixService deptHystrixService;
    @RequestMapping(value = "/consumer/dept/hystrix/ok/{id}")
    public String deptInfo_Ok(@PathVariable("id") Integer id) {
        return deptHystrixService.deptInfo_Ok(id);
    }
    //Downgrade on the client side
    @RequestMapping(value = "/consumer/dept/hystrix/timeout/{id}")
    @HystrixCommand(fallbackMethod = "dept_TimeoutHandler") //Specify a dedicated fallback method for this request
    public String deptInfo_Timeout(@PathVariable("id") Integer id) {
        String s = deptHystrixService.deptInfo_Timeout(id);
        log.info(s);
        return s;
    }
    // Dedicated fallback method of deptInfo_Timeout method
    public String dept_TimeoutHandler(@PathVariable("id") Integer id) {
        log.info("deptInfo_Timeout error, service has been downgraded!");
        return "C Language Chinese website reminds you: The server system is busy, please try again later! (Triggered by the client's deptInfo_Timeout exclusive fallback method)";
    }
}
Add configuration in 5.appliction.yml and configure the request timeout time on the client
######################### Ribbon client timeout control################# ##################
ribbon:
  ReadTimeout: 6000 #The time it takes to establish a connection. It is suitable for the time it takes for both ends to connect when the network conditions are normal.
  ConnectionTimeout: 6000 #After the connection is established, the time for the server to read the available resources
######################Configure request timeout######################## ##
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 7000
####################Configure the specific method timeout to 3 seconds ##################### ##
    DeptHystrixService#deptInfo_Timeout(Integer):
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 3000

Notice:

1.Hystrix can set the timeout (in milliseconds) for all requests (methods). If the request times out, the global fallback method will be triggered for processing.

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=mmm

2.Hystrix can also set a timeout for a specific service request (method)

hystrix.command.xxx#yyy(zzz).execution.isolation.thread.timeoutInMilliseconds=mmm

The format is explained as follows:

  • xxx: is the name of the class that contains the service method (usually the name of the service binding interface), such as the DeptHystrixService interface.
  • yyy: Service method name, such as deptInfo_Timeout() method.
  • zzz: Parameter type within the method, such as Integer, String, etc.
  • mmm: The timeout to be set, in milliseconds (1 second =1000 milliseconds)
6. Add comments to startup class
@SpringBootApplication
@EnableFeignClients //Enable OpenFeign function
@EnableHystrix //Enable Hystrix
public class MicroServiceCloudConsumerDeptFeignApplication {
    public static void main(String[] args) {
        SpringApplication.run(MicroServiceCloudConsumerDeptFeignApplication.class, args);
    }
}
7. Browser access

Global downgrade

Configuring downgrade methods for all business methods will most likely cause rapid code expansion. In order to solve this problem, we can also specify a global fallback method for all business methods

1. Annotation configuration
@Slf4j
@RestController
@DefaultProperties(defaultFallback = "dept_Global_FallbackMethod") //Global service downgrade method
public class HystrixController_Consumer {
…
}
2.Creation method

Create a global fallback method named dept_Global_FallbackMethod

/**
 * Global fallback method,
 * The fallback method must be in the same class as the execution method of hystrix
 * @DefaultProperties(defaultFallback = "dept_Global_FallbackMethod") annotation on the class, use @HystrixCommand annotation on the request method
 */
public String dept_Global_FallbackMethod() {
    return "C Language Chinese website reminds you that there is an operation error or the server system is busy, please try again later! (The client's global rollback method is triggered,)";
}

The downgrade (FallBack) method must be in the same class as its corresponding business method, otherwise it will not take effect

3. Business method annotation and annotation

Mark all business methods with the @HystrixCommand annotation, and change @HystrixCommand(fallbackMethod = “dept_TimeoutHandler”) on the deptInfo_Timeout() method to @HystrixCommand.

//Downgrade on the client side
@RequestMapping(value = "/consumer/dept/hystrix/timeout/{id}")
@HystrixCommand
public String deptInfo_Timeout(@PathVariable("id") Integer id) {
    String s = deptHystrixService.deptInfo_Timeout(id);
    log.info(s);
    return s;
}

The global degradation method has a lower priority. Only when the business method does not specify its degradation method, the global rollback method will be triggered when the service is degraded. If the business method specifies its own fallback method, then when the service is downgraded, only its own fallback method will be directly triggered instead of the global fallback method.

4. Browser access

Service circuit breaker

Introduction

The circuit breaker mechanism is a link protection mechanism to deal with service avalanches. When a service fails, the service will be downgraded, the service node will be circuit breaker, and error response information will be returned quickly. When it is detected that service access is normal, restore its link node

Fuse parameter setting

①circuitBreaker.enabled: Whether to turn on the fuse;

②circuitBreaker.requestVolumeThreshold: Turn on the circuit break after the current service fails several times, the default is 20 times;

③circuitBreaker.sleepWindowInMilliseconds: Set the circuit break time. After this time, recovery will be attempted. During the circuit break time, even if the request is correct, the downgrade method will be used;

fuse type

There are three types of fuses involved in the fuse mechanism:

fuse open

After the circuit breaker is turned on, the service will not be called during this time, but the downgrade method will be accessed directly. By setting the circuit breaker time, when the time is reached, the service will be tried to be restored.

Fuse closed

Turning off the circuit breaker means that the service is normal and will not interfere with normal service calls.

Fusible and half-open

When the circuit breaker is half open, the request can access the service. If the request is for normal access, the circuit breaker will be closed; if the request is abnormal, the circuit breaker will continue to be broken and the downgrade method will be called.

Circuit breaker

The circuit breaker mechanism is implemented through Hystrix. Hystrix will monitor the status of calls between microservices. When failed calls reach a certain proportion (for example, 20 failures within 5 seconds), the circuit breaker mechanism will be activated.

Usage steps

1. When the call error rate of the service reaches or exceeds the rate specified by Hystix (default is 50%), the fuse enters the blown open state.

2. After the fuse enters the blown open state, Hystrix will start a sleep time window. During this time window, the downgrade logic of the service will temporarily serve as the main business logic, and the original main business logic will be unavailable.

3. When there is a request to call the service again, the downgrade logic will be directly called to quickly return a failure response to avoid a system avalanche.

4. When the sleep time window expires, Hystrix will enter a semi-circuit state, allowing some requests to call the original main business logic of the service, and monitor its call success rate.

5. If the call success rate reaches the expectation, it means that the service has returned to normal, Hystrix enters the circuit breaker closed state, and the original main business logic of the service is restored; otherwise, Hystrix re-enters the circuit breaker open state, the sleep time window is re-timed, and the second to the second steps are repeated. 5 steps.

example
1. Define interface
public interface DeptService {
    // hystrix fuse example ok
    public String deptInfo_Ok(Integer id);
   
    //hystrix fuse timeout case
    public String deptInfo_Timeout(Integer id);
    // Hystrix circuit breaker case
    public String deptCircuitBreaker(Integer id);
}
2. Implement the interface

The implementation class DeptServiceImpl adds the method implementation of deptCircuitBreaker() and its fallback method

//Hystrix circuit breaker case
@Override
@HystrixCommand(fallbackMethod = "deptCircuitBreaker_fallback", commandProperties = {
        //The following parameters have default configurations in the HystrixCommandProperties class
        @HystrixProperty(name = "circuitBreaker.enabled", value = "true"), //Whether to turn on the fuse
    @HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds",value = "1000"), //Statistical time window
        @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"), //Statistical number of requests within the time window
        @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"), //Sleep time window period
        @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60"), // Within the statistical time window, the circuit breaker state will be entered when the request failure rate reaches 60%
})
public String deptCircuitBreaker(Integer id) {
    if (id < 0) {
        //When the incoming id is a negative number, an exception is thrown and the downgrade method is called.
        throw new RuntimeException("c language Chinese website reminds you that id cannot be a negative number!");
    }
    String serialNum = IdUtil.simpleUUID();
    return Thread.currentThread().getName() + "\t" + "The call was successful, the serial number is: " + serialNum;
}
//deptCircuitBreaker's downgrade method
public String deptCircuitBreaker_fallback(Integer id) {
    return "c language Chinese website reminds you that id cannot be a negative number, please try again later!\t id:" + id;
}
3. Method provides external services
// Hystrix service circuit breaker
@RequestMapping(value = "/dept/hystrix/circuit/{id}")
public String deptCircuitBreaker(@PathVariable("id") Integer id){
    String result = deptService.deptCircuitBreaker(id);
    log.info("result:" + result);
    return result;
}
4. Browser access

Fault Monitoring

Hystrix also provides a quasi-real-time call monitoring function. Hystrix will continuously record the execution information of all requests initiated through Hystrix and display it to users in the form of statistical reports, including the number of requests executed per second, the number of successful requests and failures. Requested quantity etc.

1. Add dependencies

 <!--hystrix-dashboard monitoring dependencies-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
        </dependency>

2. Add configuration in application.yml

#http://eureka7001.com:9002/hystrix fuse monitoring page
# localhost:8004//actuator/hystrix.stream monitoring address
hystrix:
  dashboard:
    proxy-stream-allow-list:
      - "localhost"

3. Add the @EnableHystrixDashboard annotation to the main startup class to enable the Hystrix monitoring function

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

4. Create configuration class

@Configuration
public class HystrixDashboardConfig {
    /**
     * Hystrix dashboard monitoring interface must be configured
     * @return
     */
    @Bean
    public ServletRegistrationBean getServlet() {
        HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
        registrationBean.setLoadOnStartup(1);
        registrationBean.addUrlMappings("/actuator/hystrix.stream");//Access path
        registrationBean.setName("hystrix.stream");
        return registrationBean;
    }
}

5. Browser access