Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Hystrix in SpringCloud. What's the use of the function?

2025-03-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article mainly introduces Hystrix. What is the use of the function? what is introduced in this article is very detailed and has a certain reference value. Interested friends must finish reading it!

I. Overview

In the micro-service architecture, we split the system into many service units, and the applications of each unit depend on each other through service registration and subscription. Since each unit runs in a different process and relies on remote invocation, there may be call failures or delays due to network reasons or depending on the service itself. These problems will directly lead to delays in the caller's external services. If the caller's requests continue to increase at this time, the task backlog will eventually be formed by waiting for the failed relying party to respond. Eventually lead to the paralysis of their own services.

So we introduce a circuit breaker, which is similar to a physical circuit. When the current is overloaded, the circuit is disconnected, which is what we commonly call "tripping". By the same token, the same is true of calls between services. When service delays, failures, and other calls that affect system performance continue to occur, the service call will be cut off!

Spring Cloud Hystrix implements a series of service protection functions such as circuit breaker, thread isolation and so on. It is also implemented based on Hystrix, the open source framework of Net subscription ix, which aims to provide stronger fault tolerance for delays and failures by controlling nodes that access remote systems, services, and third-party libraries. Hystrix has powerful functions such as service degradation, service breaker, thread and signal isolation, request caching, request merging, service monitoring and so on.

II. Hystrix work flow

1. Create HystrixCommand (when dependent services return a single operation result) or HystrixObserableCommand (when dependent services return multiple operation results) objects.

two。 Orders are carried out. HystrixComand implements the first two execution methods, while HystrixObservableCommand implements the latter two:

Execute (): execute synchronously, returning a single result object from a dependent service, or throwing an exception when an error occurs. Queue (): asynchronous execution, which directly returns a Future object containing a single result object to be returned at the end of service execution. Observe (): returns the Observable object, which represents multiple results of the operation, which is a Hot Obserable (events are published after creation, regardless of whether the "event source" has a "subscriber" or not, so each "subscriber" of the Hot Observable may start in the middle of the "event source" and may only see the local process of the whole operation). ToObservable (): the Observable object is also returned, representing multiple results of the operation, but it returns a Cold Observable (instead of publishing the event when there is no "subscriber", it waits until there is a "subscriber", so for Cold Observable subscribers, it is guaranteed to see the entire operation from the beginning).

3. If the request cache for the current command is enabled and the command cache is hit, the cached result is immediately returned as an Observable object.

4. Check whether the circuit breaker is open. If the circuit breaker is on, Hystrix does not execute the command, but goes to the fallback processing logic (step 8); if the circuit breaker is off, check if resources are available to execute the command (step 5).

5. Whether the thread pool / request queue / semaphore is full. If the command depends on the service's proprietary thread pool and request queue, or if the semaphore (when not using the thread pool) is already full, Hystrix does not execute the command, but instead transfers to the fallback processing logic (step 8).

6.Hystrix will decide how to request dependent services based on the method we write.

HystrixCommand.run (): returns a single result or throws an exception. HystrixObservableCommand.construct (): returns an Observable object to emit multiple results, or sends an error notification via onError.

7.Hystrix reports "success", "failure", "reject", "timeout" and other information to the circuit breaker, and the circuit breaker maintains a set of counters to count the data. The circuit breaker uses these statistics to decide whether to turn the circuit breaker on to "circuit breaker / short circuit" a service-dependent request.

8. When the command fails, Hystrix will enter the fallback to attempt a fallback process, which we usually call a "service degradation". There are several situations that can cause service degradation:

Step 4: the current command is in the "fuse / short circuit" state, and the circuit breaker is on. Step 5: when the thread pool, request queue, or semaphore of the current command is full. Step 6: when HystrixObservableCommand.construct () or HystrixCommand.run () throws an exception.

9. When the Hystrix command executes successfully, it returns the processing result directly or in the form of Observable.

Tips: if we do not implement the demotion logic for the command or throw an exception in the degraded processing logic, Hystrix still returns an Observable object, but it does not emit any result data, but instead informs the command to interrupt the request immediately through the onError method, and sends the exception causing the command failure to the caller through the onError () method.

III. Hystrix fuse protection mechanism

1. Assuming that a large number of requests exceed the threshold of HystrixCommandProperties.circuitBreakerRequestVolumeThreshold (), the fuse will change from closed to open.

two。 Assuming that the percentage of dependent call failures exceeds the threshold of HystrixCommandProperties.circuitBreakerErrorThresholdPercentage (), the fuse will change from the closed state to the open state

3. During the period when the fuse is open, all calls to this dependency are short-circuited, that is, no real dependency call is made and a failure is returned After waiting (cooling) exceeds the value of HystrixCommandProperties.circuitBreakerSleepWindowInMilliseconds (), the fuse will be in a half-open state, which will allow a single request to invoke the dependency. If this dependency call still fails, the fuse state will be turned on again for a duration of

The value of the 4.HystrixCommandProperties.circuitBreakerSleepWindowInMilliseconds () configuration; if this dependency call succeeds, the fuse state is turned off and subsequent dependency calls can be executed normally.

Fourth, Hystrix dependency isolation mechanism

Thread pool isolation

Hystrix uses "bulkhead mode" to achieve thread pool isolation, which creates a separate thread pool for each dependent service, so that even if the latency of a dependent service is too high, it only affects the invocation of that dependent service and does not slow down other dependent services. The disadvantage is that it involves the performance loss of thread switching, but the official result is that the performance loss is acceptable.

Semaphore isolation

Semaphore isolation can limit the maximum number of concurrent requests for dependent calls. Each dependent call will first determine whether the semaphore reaches the threshold, and reject the call if it reaches the limit. The cost of a semaphore is much less than that of a thread pool, but it cannot set a timeout and implement asynchronous access. Therefore, semaphores are used only if the dependent service is reliable enough. Here are two ways to configure semaphore isolation:

Setter mode

HystrixCommand.Setter setter = HystrixCommand.Setter .withGroupKey (HystrixCommandGroupKey.Factory.asKey ("strGroupCommand")) .andCommandKey (HystrixCommandKey.Factory.asKey ("strCommand")) .andThreadPool Key (HystrixThreadPoolKey.Factory.asKey ("strThreadPool")); / / configure semaphore isolation HystrixCommandProperties.Setter commandPropertiesSetter = HystrixCommandProperties.Setter (). WithExecutionIsolationStrategy (HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE); setter.andCommandPropertiesDefaults (commandPropertiesSetter)

Annotation mode

@ HystrixCommand (fallbackMethod = "fallbackMethod", commandProperties = {/ / set the isolation policy, THREAD means thread pool SEMAPHORE: signal pool isolation @ HystrixProperty (name = "execution.isolation.strategy", value = "THREAD"), / / when the isolation policy selects signal pool isolation, it is used to set the size (maximum concurrency) @ HystrixProperty (name = "execution.isolation.semaphore.maxConcurrentRequests", value = "10"),}).

V. hystrix actual combat

SpringBoot version number: 2.1.6.RELEASE

SpringCloud version number: Greenwich.RELEASE

1. Pom.xml

Org.springframework.cloud spring-cloud-starter-netflix-hystrix

two。 Introduce @ EnableCircuitBreaker annotation on the startup class of SpringBoot to turn on the circuit breaker function.

3. It is mentioned in the above hystrix working principle that circuit breakers can be performed in four ways:

Execute ()-synchronous execution

@ HystrixCommand (fallbackMethod = "fallbackMethod") public String strConsumer () {ResponseEntity result = restTemplate.getForEntity ("http://cloud-eureka-client/hello", String.class); return result.getBody ();}

FallbackMethod-callback method that walks into callback logic when service invocation is abnormal, circuit breaker is open, thread pool / request queue / semaphore is full. Must be defined in the same class as the service method, and there are no specific requirements for modifiers, which can be defined as private, protected, or public.

Queue ()-Asynchronous execution

@ HystrixCommand (fallbackMethod = "fallbackMethod", ignoreExceptions = {IllegalAccessException.class}) public Future asyncStrConsumer () {Future asyncResult = new AsyncResult () {@ Override public String invoke () {ResponseEntity result = restTemplate.getForEntity ("http://cloud-eureka-client/hello", String.class); return result.getBody ();}}; return asyncResult;}

IgnoreExceptions means that the degraded callback logic is not used when the exception is thrown, and the exception is ignored.

Observe () execution mode

@ HystrixCommand (observableExecutionMode = ObservableExecutionMode.EAGER) protected Observable construct () {ResponseEntity result = restTemplate.getForEntity ("http://cloud-eureka-client/hello", String.class); return Observable.just (result.getBody ());}

ToObservable () execution mode

@ HystrixCommand (observableExecutionMode = ObservableExecutionMode.LAZY) protected Observable construct () {ResponseEntity result = restTemplate.getForEntity ("http://cloud-eureka-client/hello", String.class); return Observable.just (result.getBody ());}

4. Command name, grouping, and thread pool partition

Hystrix will organize and count the alarm, dashboard and other information of the command according to the group.

By default, Hystrix causes commands with the same group name to use the same thread pool.

In general, try to specify the partition of the thread pool through HystrixThreadPoolKey, rather than by the default of the group name, because several different commands may belong to the same group in terms of business logic, but often need to be isolated from other commands from the implementation itself.

@ HystrixCommand (fallbackMethod = "fallbackMethod", groupKey = "strGroupCommand", commandKey = "strCommand", threadPoolKey = "strThreadPool") public String strConsumer (@ CacheKey Long id) {ResponseEntity result = restTemplate.getForEntity ("http://cloud-eureka-client/hello", String.class); return result.getBody ();}

GroupKey defaults to the class name, commandKey defaults to the method name, and threadPoolKey defaults to groupKey.

5. Request cache and request merge

5.1 request caching

There is really no need to say much about the functions and benefits of caching. Request caching, as the name implies, caches the results of requests for the same key. Then the next request for this key, the data will be returned directly in the cache, reducing the response time.

There are three main annotations to use caching in Hystrix: @ CacheResult, @ CacheKey, and @ CacheRemove

CacheResult: used to mark that the request result should be cached and must be used with @ HystrixCommand. @ CacheKey: used to modify the method parameter to indicate the cached key name, which takes precedence over the key name set by @ CacheResult. CacheRemove: when the data is updated, we need to invalidate the cache for the sake of data consistency. @ CacheRemove is used to mark the cache expiration of the request result (commandKey is a required parameter indicating the cache key to be invalidated).

@ CacheResult (cacheKeyMethod = "getCacheKey") @ HystrixCommand (fallbackMethod = "fallbackMethod") public String strConsumer (@ CacheKey Long id) {ResponseEntity result = restTemplate.getForEntity ("http://cloud-eureka-client/hello", String.class); return result.getBody ();}

5.2 request for merge

Dependency in microservice architecture is usually achieved through remote invocation, and the most common problems in remote invocation are communication consumption and connection occupation.

In the case of high concurrency, the total communication time consumption will become less ideal due to the increase of communication times. At the same time, because the thread pool resources that depend on the service are limited, there will be queues and response delays. To optimize these two issues, Hystrix provides HystrixCollapser to merge requests to reduce communication consumption and thread usage.

@ RestControllerpublic class UserConsumer {@ Autowired private UserService userService / * obtain the user interface * * @ param id * @ return * / @ HystrixCollapser (batchMethod = "getByIds", collapserProperties = {/ / 10ms) into a batch request @ HystrixProperty (name = "timerDelayInMilliseconds", value = "10"), / / whether to enable caching @ HystrixProperty (name = "requestCache.enabled", value = "10"),}) public String getById (Long id) {return userService.getUserById (id) } / * obtain user information in batch via ids API * * @ param ids id collection * @ return * / @ HystrixCommand public Set getByIds (List ids) {return userService.getUserByIds (ids);}}

Although the number of requests can be reduced by request merging to alleviate the resources dependent on the service thread pool, however, it is also important to pay attention to the additional overhead when using it: the delay time window used to request merging increases the latency of requests that depend on services.

Whether to enable cache merge or not, we generally consider the following two factors:

If the service-dependent request command itself is a high-latency command, you can use the request combiner because the time window consumption is negligible because of the high latency. If there are only 1-2 requests in a time window, such a dependent service is not suitable for using the request combiner. Instead of improving system performance, this situation will become a system bottleneck; on the contrary, if there is a high concurrency in a time window, and the service provider also implements a batch processing interface, then the use of request combiner can effectively reduce the number of network connections and greatly improve system throughput.

6. Introduction to HystrixCommand attribute

@ HystrixCommand (fallbackMethod = "fallbackMethod", groupKey = "strGroupCommand", commandKey = "strCommand", threadPoolKey = "strThreadPool", commandProperties = {/ / set the isolation policy, THREAD indicates thread pool SEMAPHORE: signal pool isolation @ HystrixProperty (name = "execution.isolation.strategy", value = "THREAD"), / / when the isolation policy selects signal pool isolation Used to set the size of the signal pool (maximum concurrency) @ HystrixProperty (name = "execution.isolation.semaphore.maxConcurrentRequests", value = "10"), / / configure the timeout of command execution @ HystrixProperty (name = "execution.isolation.thread.timeoutinMilliseconds", value = "10"), / / whether the timeout @ HystrixProperty is enabled (name = "execution.timeout.enabled", value = "true") / / whether @ HystrixProperty is interrupted when execution times out (name = "execution.isolation.thread.interruptOnTimeout", value = "true"), / / whether @ HystrixProperty is interrupted when execution is cancelled (name = "execution.isolation.thread.interruptOnCancel", value = "true"), / / the maximum number of concurrency allowed for callback method execution @ HystrixProperty (name = "fallback.isolation.semaphore.maxConcurrentRequests", value = "10"), / / whether service degradation is enabled Whether to execute the callback function @ HystrixProperty (name = "fallback.enabled", value = "true"), / / whether to enable the circuit breaker @ HystrixProperty (name = "circuitBreaker.enabled", value = "true"), / / this property is used to set the minimum number of requests for circuit breakers in the rolling time window. For example, when the default value is 20, if only 19 requests are received within the scroll time window (default 10 seconds), even if all 19 requests fail, the circuit breaker will not open. @ HystrixProperty (name = "circuitBreaker.requestVolumeThreshold", value = "20"), / / this property is set in the scrolling time window, indicating that if the percentage of error requests exceeds 50 in the scrolling time window, if the percentage of error requests exceeds 50, the circuit breaker is set to "on", otherwise it is set to "off". @ HystrixProperty (name = "circuitBreaker.errorThresholdPercentage", value = "50"), / / this property is used to set the sleep window when the circuit breaker is turned on. After the hibernation time window ends, the circuit breaker is set to "half open", the request command for fuse is attempted, and if it still fails, the circuit breaker continues to be set to "on" and to "off" if successful. @ HystrixProperty (name = "circuitBreaker.sleepWindowinMilliseconds", value = "5000"), / / Circuit Breaker forced to open @ HystrixProperty (name = "circuitBreaker.forceOpen", value = "false"), / / Circuit Breaker forced to close @ HystrixProperty (name = "circuitBreaker.forceClosed", value = "false"), / / scroll time window setting This time is used for the duration time @ HystrixProperty (name = "metrics.rollingStats.timeinMilliseconds", value = "10000") that the circuit breaker needs to collect information when judging the health degree. / / this attribute is used to divide the number of "buckets" when setting the rolling time window statistical index information. When collecting the index information, the circuit breaker will split into multiple "buckets" according to the set time window length to accumulate each measurement value. Each barrel records the collection index over a period of time. / / for example, split into 10 "buckets" within 10 seconds to collect, so timeinMilliseconds must be divisible by numBuckets. Otherwise, an exception @ HystrixProperty (name = "metrics.rollingStats.numBuckets", value = "10") is thrown, and / / this property is used to set whether the delay in command execution is tracked and calculated using a percentile. If set to false, all profile statistics will return-1. @ HystrixProperty (name = "metrics.rollingPercentile.enabled", value = "false"), / / this property is used to set the duration of the scrolling window for percentile statistics in milliseconds. @ HystrixProperty (name = "metrics.rollingPercentile.timeInMilliseconds", value = "60000"), / / this property is used to set percentile statistics on the number of "buckets" used in the scroll window. @ HystrixProperty (name = "metrics.rollingPercentile.numBuckets", value = "60000"), / / this property is used to set the maximum number of executions retained in each "bucket" during execution. If the number of times of execution exceeds the set value within the scrolling time window, / / it is rewritten from the original position. For example, if the value is set to 100 and the scroll window is set to 10 seconds, if 500 executions occur in a "bucket" within 10 seconds, then only the statistics of the last 100 executions are retained in the "bucket". In addition, increasing the size of this value will increase the consumption of memory and increase the calculation time required to sort the percentile. @ HystrixProperty (name = "metrics.rollingPercentile.bucketSize", value = "100"), / / this attribute is used to set the interval waiting time to take healthy snapshots (success of requests, percentage of errors) that affect the status of circuit breakers. @ HystrixProperty (name = "metrics.healthSnapshot.intervalinMilliseconds", value = "500"), / / whether to enable request cache @ HystrixProperty (name =" requestCache.enabled ", value =" true "), / / whether the execution and events of HystrixCommand print logs to HystrixRequestLog @ HystrixProperty (name =" requestLog.enabled ", value =" true "),}, threadPoolProperties = {/ / this parameter is used to set the number of core threads in the command thread pool. This value is the maximum concurrency of command execution @ HystrixProperty (name = "coreSize", value = "10"), and / / this parameter is used to set the maximum queue size of the thread pool. When set to-1, the thread pool uses the queue implemented by SynchronousQueue, otherwise the queue implemented by LinkedBlockingQueue will be used. @ HystrixProperty (name = "maxQueueSize", value = "- 1"), / / this parameter is used to set the reject threshold for the queue. With this parameter, the request can be rejected even if the queue does not reach the maximum. / / this parameter is mainly a supplement to the LinkedBlockingQueue queue, because the LinkedBlockingQueue queue cannot dynamically modify its object size, and this property allows you to adjust the queue size of rejected requests. @ HystrixProperty (name = "queueSizeRejectionThreshold", value = "5"),}) public String strConsumer () {ResponseEntity result = restTemplate.getForEntity ("http://cloud-eureka-client/hello", String.class); return result.getBody ();}

The above is all the contents of the article "what is the use of Hystrix in SpringCloud?" Thank you for reading! Hope to share the content to help you, more related knowledge, welcome to follow the industry information channel!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report