[Microservice Notes 07] Hystrix of microservice components implements request caching function

This article mainly introduces the request caching function implemented by Hystrix of microservice components.

Table of contents

1. Introduction to Hystrix components

1.1, what is Hystrix

1.2, the function of Hystrix

2. Hystrix implements request caching (understanding)

2.1. Introduction to request caching

2.2. Introducing dependencies

2.3, service layer code

(1) The first cache implementation

(2) The second cache implementation

2.4, control layer code

(1) The control layer uses HystrixRequestContext

(2) The filter uses HystrixRequestContext

2.5, open the hystrix function

2.6. Cache deletion


1. Introduction to Hystrix components

1.1, what is Hystrix

In a microservice environment, calls between services may be very frequent. If a microservice has a lot of requests and the microservice cannot handle it, then the server may be down at this time. In the event of a downtime, other microservice systems that call this microservice will also be affected. The requests in the microservice have been backlogged, which will cause all microservice systems to crash. We call this situation Yes: an avalanche of services.

In order to avoid service avalanche and improve the high availability of microservices, Hystrix service fault-tolerant components appeared. Hystrix provides a variety of functions, such as: request caching, request merging, thread pool isolation, semaphore isolation, service degradation, service fusing , service monitoring, etc.

  • PS: The English word Hystrix means porcupine.

1.2, the function of Hystrix

The functions provided by Hystrix are roughly as follows:

  • Request cache: The returned result can be temporarily cached according to the requested URI, and the next time the same URI is requested, the data will be obtained from the cache.
  • Request merging: Multiple requests from the client can be combined into one request, and the server interface can be called in batch mode.
  • Thread pool isolation: Different requests are isolated by different thread pools, so that even if there is a problem with one of the thread pool requests, it will not affect the requests of other thread pools.
  • Semaphore isolation: Too many thread pools in the project will reduce performance, because the thread pool needs to switch threads back and forth, so the semaphore isolation mechanism is proposed.
  • Service degradation: When a problem occurs during service invocation, alternative methods can be called to achieve fast failure return.
  • Service fuse: There is a fuse in Hystrix. When other microservices are unavailable, the fuse will be turned on. At this time, all call requests will be blocked, and the failure will be returned quickly.
  • Service monitoring: Hystrix provides a dashboard control panel that can monitor and view the invocation of requests.

2. Hystrix implements request caching (understanding)

The request cache provided by Hystrix is ​​a local cache, which is not applicable in a distributed environment, and in actual development, the request cache function of hystrix will not be used, because this function is too redundant, and Hystrix's request cache can only be used in the same request It only takes effect under the request scope, and the next request request will clear the request cache of the previous request. The following describes how to use Hystrix to implement the request caching function.

2.1. Introduction to request caching

hystrix request caching means: under the same request request, when calling other microservices multiple times, the result of the first call will be cached, and then the data result will be obtained from the cache each time.

It can be understood that what hystrix caches is the return result of the service layer method. When the service layer method is called multiple times in the same HTTP request in the controller layer, the data will be obtained from the cache at this time.

What is the same HTTP request? ? ?

  • A user visits the address [/api/demo], and the request enters the controller layer at this time, and then we call the method of the service layer twice in the method of the controller layer, then the second call of the method of the service layer returns the value at this time, Will be fetched from the hystrix cache.
  • In the above case, it is only in one HTTP request. If the user visits [/api/demo] twice, then it is not the same HTTP request at this time, and the cached data of the first time will be cached by the second time. The cached data is overwritten.
  • Of course, the premise is that this method enables the request caching function.

2.2. Introducing dependencies

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

2.3, service layer code

In the service layer, there are two ways to specify the function that needs to enable request caching, namely:

  • The first method: use the [@HystrixCommand] annotation, [@CacheResult] annotation, and the cacheKeyMethod attribute in the @CacheResult annotation.
  • The second method: use [@HystrixCommand] annotation, [@CacheResult] annotation, [] annotation.

The difference between the two methods is: the way to set the cache key is different, one is to specify the cache key through annotations, and the other is through a custom method.

(1) The first cache implementation

package com.gitcode.hystrix.service;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.cache.annotation.CacheResult;
import org.springframework.stereotype.Service;

import java.security.SecureRandom;

/**
 * @version 1.0.0
 * @Date: 2023/4/7 20:54
 * @Copyright (C) ZhuYouBin
 * @Description: hystrix 请求缓存案例
 */
@Service
public class HystrixCacheService {


    // 将当前方法的返回保持到缓存里面
    @CacheResult(cacheKeyMethod = "getCacheKey")
    @HystrixCommand(commandKey = "requestCacheKey") // 声明当前方法需要执行 hystrix 命令
    public String requestCache(String id) {
        // TODO 这里可以调用其他的微服务完成一些业务逻辑功能
        // 为了简单些,我这里就生产一个随机数作为返回值
        SecureRandom random = new SecureRandom();
        return random.nextInt() + "";
    }

    /**
     * 定义获取 缓存key 的方法
     * <p>
     *     注意:获取缓存key的方法参数必须和开启请求缓存方法的参数列表相同
     * </p>
     */
    public String getCacheKey(String id) {
        return id;
    }

}

(2) The second cache implementation

// 将当前方法的返回保持到缓存里面
@CacheResult
@HystrixCommand(commandKey = "requestCacheKey") // 声明当前方法需要执行 hystrix 命令
public String requestCache(@CacheKey String id) { // 将当前参数作为缓存key
    // TODO 这里可以调用其他的微服务完成一些业务逻辑功能
    // 为了简单些,我这里就生产一个随机数作为返回值
    SecureRandom random = new SecureRandom();
    return random.nextInt() + "";
}

Note: If no cache key is specified, hystrix will use all parameters in the current method as the cache key at this time.

2.4, control layer code

Because the request cache of hystrix must be in the same request, the [HystrixRequestContext] class provided by hystrix must be used to initialize the request context, and the cache needs to be cleared after each request ends.

If you use the HystrixRequestContext class to initialize the context in the controller every time, there will be a lot of repeated code, so in order to simplify the code, you can generally use the HystrixRequestContext class in a filter to complete the context initialization and cache clearing functions.

  • Note: If the HystrixRequestContext class is not used, an exception will be thrown.
Request caching is not available. Maybe you need to initialize the HystrixRequestContext?

(1) The control layer uses HystrixRequestContext

package com.gitcode.hystrix.controller;

import com.gitcode.hystrix.service.HystrixCacheService;
import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @version 1.0.0
 * @Date: 2023/4/7 21:09
 * @Copyright (C) ZhuYouBin
 * @Description:
 */
@RestController
@RequestMapping("/api/hystrix")
public class HystrixController {
    
    @Autowired
    private HystrixCacheService hystrixCacheService;

    @GetMapping("/cache")
    public String hystrixCache() {
        // 1、开启hystrix请求上下文
        HystrixRequestContext context = HystrixRequestContext.initializeContext();
        // 2、TODO 在这之间,就可以多次调用service层代码
        String rtn = hystrixCacheService.requestCache("1001");
        System.out.println("第一次调用返回结果: " + rtn);

        // 参数相同的情况下,第二次调用的返回值是从缓存获取的,所以必定和第一次的返回值相同
        rtn = hystrixCacheService.requestCache("1001");
        System.out.println("第二次调用返回结果: " + rtn);
        
        // 注意: 入参不同
        rtn = hystrixCacheService.requestCache("1002");
        System.out.println("第三次调用返回结果: " + rtn);

        // 3、清除缓存
        context.close();
        return "success";
    }

}

(2) The filter uses HystrixRequestContext

package com.gitcode.hystrix.filter;

import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext;

import javax.servlet.*;
import java.io.IOException;

/**
 * @version 1.0.0
 * @Date: 2023/4/7 21:23
 * @Copyright (C) ZhuYouBin
 * @Description: hystrix请求缓存过滤器
 */
public class HystrixCacheFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HystrixRequestContext context = null;
        try {
            // 开启 hystrix 请求上下文
            context = HystrixRequestContext.initializeContext();
            // 继续执行后面代码
            chain.doFilter(request, response);
        } finally {
            if (null != context) {
                // 每次请求结束,清除缓存
                context.close();
            }
        }
    }
}
  • SpringBoot can inject this filter into the IOC container.
package com.gitcode.hystrix.config;

import com.gitcode.hystrix.filter.HystrixCacheFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;

/**
 * @version 1.0.0
 * @Date: 2023/4/7 21:40
 * @Copyright (C) ZhuYouBin
 * @Description:
 */
@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean<HystrixCacheFilter> hystrixCacheFilter() {
        FilterRegistrationBean<HystrixCacheFilter> registration = new FilterRegistrationBean<>();
        registration.setFilter(new HystrixCacheFilter());
        registration.addUrlPatterns("/*");
        registration.setName("HystrixCacheFilter");
        // 设置优先级别
        registration.setOrder(Ordered.LOWEST_PRECEDENCE);
        return registration;
    }

}

2.5, open the hystrix function

On the startup class, you need to use the [@EnableCircuitBreaker] annotation or [@EnableHystrix] annotation to enable the hystrix fuse function, otherwise hystrix will not take effect. The functions of the two annotations are the same. The @EnableHystrix annotation already includes the @EnableCircuitBreaker annotation, but the official use is the @EnableCircuitBreaker annotation, so we follow the official usage and directly use the @EnableCircuitBreaker annotation to enable the function.

2.6. Cache deletion

hystrix also provides the annotation @CacheRemove to delete the cache. When some new, delete, and update operations are performed, the data in the cache may not be the latest at this time, so the data in the cache needs to be deleted at this time. Use the [@CacheRemove] annotation and specify the [commandKey] attribute at the same time, which tells hystrix which command to delete all caches under.

  • Note: The commanKey here needs to be the same as the commanKey attribute specified in the @HystrixCommand annotation in the request cache.
/**
 * 删除 commandKey 等于 requestCacheKey 中的所有缓存
 */
@CacheRemove(commandKey = "requestCacheKey")
public void updateData() {
    // TODO 做一些更新操作
}

At this point, the introduction of Hystrix's implementation of request caching is over.

In summary, this article is over, mainly introducing Hystrix, a microservice component, to implement the request caching function.

Guess you like

Origin blog.csdn.net/qq_39826207/article/details/130019705