[Zero to One Series] Microservice Hystrix fuse integration

Previous review:

[Zero to One Series] springcloud microservices integrate nacos to form a distributed system

1. hystrix dependency package

First, introduce hystrix-related dependency packages. The version should correspond to the one in the project. I use the default version directly here.

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

Then, the microservices demonstrated are still taking the two sub-modules in my architecture project as an example, the user module and the send module:

user module: caller

send module: callee

2. hystrix configuration

2.1 feign integrated hystrix fuse (unified configuration)

First, write a feign interface fallback implementation class of the send module, for example:

package com.***.common.hystrix;

import com.***.common.bean.ResultBean;
import com.***.common.enums.ResponseCodeEnum;
import com.***.common.feign.SendFeignClient;
import org.springframework.stereotype.Component;

@Component
public class SendFallBack implements SendFeignClient {
@Override
public ResultBean sendSMS() {
//todo can be written in the corresponding method to use a unified downgrade strategy, or a specified downgrade strategy.
return ResultBean.returnResult(ResponseCodeEnum.SUCCESS,"The sending service is temporarily disconnected, please wait...");
}
}

Then, directly configure the corresponding downgrade implementation class on the annotation of the feign interface of the send module, as follows:

@FeignClient(name = "${sys.serviceName.send}",path = "${sys.serviceContext.send}",fallback = SendFallBack.class)

Finally, in the user module, configure:

feign.hystrix.enabled=true

Now, start 2 microservices and let’s test the effect:
1. When both services are shown to be normal, the calling results are as follows:

2. Through the nacos management interface, we manually offline the send module service, or manually stop the send service to simulate abnormal service downtime, and then look at the request effect:

It can be seen that the downgrade processing of hystrix configuration integrated through feign has taken effect.

2.2 Specify interface custom fuse configuration

Here we take the send module as an example. . On the startup class, first add annotations:

@EnableHystrix

Then, write a test method as follows:

@HystrixCommand(fallbackMethod = "failResult",commandProperties =
{@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000"),
@HystrixProperty(name = "fallback.enabled", value = "true")})
@PostMapping(value = "/testHystrix")
public ResultBean testHystrix() throws InterruptedException {
//The thread sleeps for 2 seconds to simulate the slow response of the interface.
Thread.sleep(2000);
return ResultBean.returnResult(ResponseCodeEnum.SUCCESS,"send service is normal...");
}

private ResultBean failResult(){
return ResultBean.returnResult(ResponseCodeEnum.FAIL,"send service is temporarily unavailable...");
}

After starting, let’s test it:

It can be seen that the execution of the interface has entered the downgraded fallback method.

Here, I will post the detailed configuration instructions of HystrixCommand for reference:

The

Command attribute is mainly used to control the behavior of the HystrixCommand command. It is mainly divided into the following categories:

1. Execution: used to control the execution of HystrixCommand.run()
execution.isolation.strategy: This property is used to set the isolation strategy executed by HystrixCommand.run(). Default is THREAD.
execution.isolation.thread.timeoutInMilliseconds: This property is used to configure the timeout period for HystrixCommand execution, in milliseconds.
execution.timeout.enabled: This property is used to configure whether the execution of HystrixCommand.run() enables timeout. Default is true.
execution.isolation.thread.interruptOnTimeout: This property is used to configure whether HystrixCommand.run() should be interrupted when its execution times out.
execution.isolation.thread.interruptOnCancel: This property is used to configure whether HystrixCommand.run() should be interrupted when its execution is canceled.
execution.isolation.semaphore.maxConcurrentRequests: When the isolation strategy of the HystrixCommand command uses a semaphore, this property is used to configure the size of the semaphore. When the maximum concurrent requests reach this setting value, subsequent requests will be rejected.

2. Fallback: used to control the execution of HystrixCommand.getFallback()
fallback.isolation.semaphore.maxConcurrentRequests: This property is used to set the maximum number of concurrent requests allowed to be executed by the HystrixCommand.getFallback() method from the calling thread. When the maximum concurrent requests are reached, subsequent requests will be rejected and an exception will be thrown.
fallback.enabled: This attribute is used to set whether the service downgrade policy is enabled. The default is true. If set to false, when a request fails or a rejection occurs, HystrixCommand.getFallback() will not be called to perform service degradation logic.

3. Circuit Breaker: used to control the behavior of HystrixCircuitBreaker.
circuitBreaker.enabled: Determines whether to use a circuit breaker to track its health indicators and circuit breaker requests when a service request command fails. Default is true.
circuitBreaker.requestVolumeThreshold: used to set the minimum number of requests for the circuit breaker to blow in the rolling time window. For example, when the default value is 20, if only 19 requests are received within the rolling time window (default 10 seconds), even if all 19 requests fail, the circuit breaker will not be opened.
circuitBreaker.sleepWindowInMilliseconds: used to set the sleep time window after the circuit breaker is opened. After the sleep time window is over, the circuit breaker will be set to the "half-open" state, and the fuse request command will be tried. If it still fails, the circuit breaker will continue to be set to the "open" state. If successful, it will be set to the "off" state.
circuitBreaker.errorThresholdPercentage: This property is used to set the error percentage condition for circuit breaker opening. The default value is 50, which means that in the rolling time window, under the premise that the request value exceeds the requestVolumeThreshold threshold, if the percentage of incorrect requests exceeds 50, the circuit breaker is set to the "open" state, otherwise it is set to the "off" state.
circuitBreaker.forceOpen: This property defaults to false. If this property is set to true, the circuit breaker is forced into the "open" state, where it denies all requests. This attribute is superior to the forceClosed attribute.
circuitBreaker.forceClosed: This property defaults to false. If this property is set to true, the circuit breaker is forced into the "off" state and it receives all requests. If the forceOpen attribute is true, this attribute does not take effect.

4. Metrics: This attribute is related to the metrics captured during the execution of HystrixCommand and HystrixObservableCommand.
metrics.rollingStats.timeInMilliseconds: This property is used to set the length of the rolling time window in milliseconds. This time is used for the duration of information that the circuit breaker needs to collect when determining its health. When collecting indicator information, the circuit breaker will split it into multiple buckets according to the set time window length to accumulate each metric value. Each bucket records the collected indicators for a period of time. For example, when the default value is 10000 milliseconds, the circuit breaker divides it into 10 buckets by default, and each bucket records indicator information within 1000 milliseconds.
metrics.rollingStats.numBuckets: used to set the number of "buckets" divided into when rolling time window statistical indicator information. The default value is 10.
metrics.rollingPercentile.enabled: Used to set whether to use percentiles to track and calculate command execution delays. The default is true. If set to false, all summary statistics will return -1.
metrics.rollingPercentile.timeInMilliseconds: used to set the duration of the rolling window for percentile statistics, in milliseconds.
metrics.rollingPercentile.numBuckets: used to set the number of buckets used in the rolling window of percentile statistics.
metrics.rollingPercentile.bucketSize: used to set the maximum number of executions retained in each "bucket".
metrics.healthSnapshot.intervalInMilliseconds: used to set the interval waiting time for collecting health snapshots that affect the circuit breaker status.

5. Request Context: Involves the setting of HystrixCommand using HystrixRequestContext.
requestCache.enabled: used to configure whether to enable request caching.
requestLog.enabled: used to set the execution of HystrixCommand and whether events are printed to the HystrixRequestLog of the log.

3. Hystrix configuration parameter description

1.HystrixCommandProperties are used for HystrixCommand configuration, and one HystrixCommandKey corresponds to one HystrixCommandProperties instance.

2.HystrixThreadPoolProperties are used for HystrixThreadPool configuration. One HystrixThreadPoolKey corresponds to one HystrixThreadPoolProperties instance.

3.HystrixCollapserProperties are used for HystrixCollapserCommand configuration, and one HystrixCollapserKey corresponds to one HystrixCollapserProperties instance.

category

Configuration items

default value

HystrixCommandProperties

hystrix.threadpool.[commandkey].circuitBreaker.enabled

true

hystrix.threadpool.[commandkey].circuitBreaker.requestVolumeThreshold

20

hystrix.threadpool.[commandkey].circuitBreaker.sleepWindowInMilliseconds

5000

hystrix.threadpool.[commandkey].circuitBreaker.errorThresholdPercentage

50

hystrix.threadpool.[commandkey].circuitBreaker.forceOpen

false

hystrix.threadpool.[commandkey].circuitBreaker.forceClosed

false

hystrix.threadpool.[commandkey].execution.isolation.strategy

Thread

hystrix.threadpool.[commandkey].execution.isolation.thread.timeoutInMilliseconds

1000

hystrix.threadpool.[commandkey].execution.timeout.enabled

true

hystrix.threadpool.[commandkey].execution.isolation.thread.interruptOnTimeout

true

hystrix.threadpool.[commandkey].execution.isolation.thread.interruptOnFutureCancel

false

hystrix.threadpool.[commandkey].execution.isolation.semaphore.maxConcurrentRequests

10

hystrix.threadpool.[commandkey].fallback.isolation.semaphore.maxConcurrentRequests

10

hystrix.threadpool.[commandkey].fallback.enabled

true

hystrix.threadpool.[commandkey].metrics.rollingStats.timeInMilliseconds

10000

hystrix.threadpool.[commandkey].metrics.rollingStats.numBuckets

10

hystrix.threadpool.[commandkey].metrics.rollingPercentile.enabled

true

hystrix.threadpool.[commandkey].metrics.rollingPercentile.timeInMilliseconds

60000

hystrix.threadpool.[commandkey].metrics.rollingPercentile.numBuckets

6

hystrix.threadpool.[commandkey].metrics.rollingPercentile.bucketSize

100

hystrix.threadpool.[commandkey].metrics.healthSnapshot.intervalInMilliseconds

500

hystrix.threadpool.[commandkey].requestCache.enabled

true

hystrix.threadpool.[commandkey].requestLog.enabled

true

hystrix.threadpool.[commandkey].threadPoolKeyOverride

HystrixThreadPoolProperties

hystrix.threadpool.[threadPoolkey].coreSize

10

hystrix.threadpool.[threadPoolkey].allowMaximumSizeToDivergeFromCoreSize

false

hystrix.threadpool.[threadPoolkey].maximumSize

10

hystrix.threadpool.[threadPoolkey].keepAliveTimeMinutes

1

hystrix.threadpool.[threadPoolkey].maxQueueSize

-1

hystrix.threadpool.[threadPoolkey].queueSizeRejectionThreshold

5

hystrix.threadpool.[threadPoolkey].metrics.rollingStats.timeInMilliseconds

10000

hystrix.threadpool.[threadPoolkey].metrics.rollingStats.numBuckets

10

HystrixCollapserProperties

hystrix.collapser.[collapserCommandkey].maxRequestsInBatch

Integer.MAX_VALUE

hystrix.collapser.[collapserCommandkey].timerDelayInMilliseconds

10

hystrix.collapser.[collapserCommandkey].requestCache.enabled

true

hystrix.collapser.[collapserCommandkey].metrics.rollingStats.timeInMilliseconds

10000

hystrix.collapser.[collapserCommandkey].metrics.rollingStats.numBuckets

10

hystrix.collapser.[collapserCommandkey].metrics.rollingPercentile.enabled

true

hystrix.collapser.[collapserCommandkey].metrics.rollingPercentile.timeInMilliseconds

60000

hystrix.collapser.[collapserCommandkey].metrics.rollingPercentile.numBuckets

6

hystrix.collapser.[collapserCommandkey].metrics.rollingPercentile.bucketSize

100

Internally, each property is represented by a ChainHystrixProperty. ChainHystrixProperty is a concatenated HystrixDynamicProperty that continues to obtain the property value in the string until it obtains a value that is not null. The HystrixDynamicProperty concatenated by ChainHystrixProperty is obtained by default from the HystrixDynamicProperties obtained by the plug-in (we will talk about plug-ins in the end).

HystrixDynamicProperty represents dynamic configuration data. If the configuration source sends changes, the configuration obtained through this object will also change accordingly. There is an implementation class in hystrix:

1. Obtain configuration items through archaius and create the HystrixDynamicProperty class through HystrixDynamicPropertiesArchaius.

2. Obtain configuration items through system implementation, and create the HystrixDynamicProperty class through HystrixDynamicPropertiesSystemProperties.

There is also yaml configuration:

hystrix:
  command:
    #Global default configuration
    default:
      execution:
        timeout:
          #Whether to set a timeout for method execution, the default is true. Generally we don't want to change it.
          enabled: true
        isolation:
          #Configure the request isolation method, here is the default thread pool method. There is another semaphore method, semaphore, which is rarely used.
          strategy: threadPool
          semaphore:
            maxConcurrentRequests: 1000
          thread:
            #The timeout for method execution is 1000 milliseconds by default. In actual scenarios, it needs to be set according to the situation.
            timeoutInMilliseconds: 60000
            #Whether to interrupt the execution of the method when a timeout occurs, the default value is true. Don't change it.
            interruptOnTimeout: true
            #Whether to interrupt the method when the method execution is canceled, the default value is false. It has no practical meaning, just default!
            interruptOnCancel: false
            #Fuse related configuration
      ##Maximum number of threads for concurrent execution, default 10
      coreSize: 200
      #Description: Whether to allow the thread pool to expand to the maximum number of thread pools, the default is false.
      allowMaximumSizeToDivergeFromCoreSize: true
      #Description: The maximum number of threads in the thread pool, the default value is 10. This configuration item will not take effect when configured alone. AllowMaximumSizeToDivergeFromCoreSize needs to be enabled.
      maximumSize: 200
      #Description 1: The maximum value of the job queue, the default value is -1. Indicates that the queue will use SynchronousQueue. At this time, the value is 0 and Hystrix will not store jobs in the queue.
      #Explanation 2: If this value is set to a positive int type, the queue will use a fixed-size LinkedBlockingQueue. At this time, when the core thread pool is busy, the job will be temporarily stored in this queue, but the size of the queue will exceed the limit of this queue. The request will still be rejected
      maxQueueSize: 20000
      #Set the threshold for queue rejection requests, the default is 5.
      queueSizeRejectionThreshold: 30000
 
      circuitBreaker:
        #Description: Whether to activate the fuse, the default is true. The purpose of using Hystrix is to use fuses. Don't change it, otherwise we won't introduce Hystrix.
        enabled: true
        #Note 1: The minimum number of requests within the window time of enabling the circuit breaker function. Assume that the window time we set is 10 seconds.
        #Note 2: If the default value is 20 at this time, the fuse will not be opened even if 19 requests fail within 10 seconds.
        #Note 3: This configuration item needs to be calculated based on the QPS of the interface. If the value is too small, the fuse may be opened by mistake. If the value is too large and exceeds the total number of requests within the time window, the fuse will never be triggered.
        #Note 4: The recommended setting is generally: QPS*window description*60%
        requestVolumeThreshold: 3000
        #Note 1: After the fuse is opened, all requests will be quickly failed, but when the service is restored is a question. After the fuse is opened, Hystrix will release a request after a period of time.
        #Note 2: If the request can be executed successfully, it means that the service may have returned to normal at this time, and the fuse will be closed; otherwise, if the execution fails, it is considered that the service is still unavailable and the fuse will remain open.
        #Note 3: So the function of this configuration is to specify how long a request is allowed to be executed after the fuse is turned on. The official default configuration is 5 seconds.
        sleepWindowInMilliseconds: 5000
        #Note 1: This configuration refers to determining whether the fuse needs to be opened based on this configuration after obtaining the probability of Hystrix method execution failure in the current time period through the sliding window.
        #Note 2: The official default configuration here is 50, that is, after more than 50% of the requests fail within the window time, the fuse will be opened to quickly fail subsequent requests.
        errorThresholdPercentage: 70
        #Description: Whether to force the fuse to be enabled, the default is false, there is no scenario that requires this configuration, ignore it!
        forceOpen: false
        #Description: Whether to forcibly close the fuse, the default is false, there is no scenario that requires this configuration, ignore it!
        forceClosed: false

If you are interested in the implementation principles of hystrix, you can read my previous blog posts:

[SpringCloud Microservice Series] The underlying principle of Hystrix fuse

At this point, the operation process of integrating hystrix fuse with springcloud microservice has been recorded. In the future, there will be integration of distributed link tracking. If you are interested, please help with one click and three links. Thank you~~~

The knowledge points of the article match the official knowledge files, and you can further learn related knowledge. Java Skill TreeHomepageOverview 138147 people are learning the system