Based request cache request caching technology to optimize product data batch query interface

Copyright: ~ reproduced please marked, thank you - if infringement please private letter to me, I will immediately delete ~ https://blog.csdn.net/baidu_26954625/article/details/90634269

本系列内容转载自git项目advancejava
Hystrix command 8 big step when performing the third step is to check whether there Request cache buffer.

First, there is a concept called Request Context request context, generally speaking, in a web application, if we use Hystrix, we will be in a filter inside each request applied to a request context. That is, each request is a request context. Then in the context of the request, we will go to perform multi-code N, N more dependent on service calls, some dependent services may also call several times.

In the context of a request, if there are multiple command, the parameters are the same, calling the interface is the same, and the result can be considered the same. So this time, we have the first results of command execution returning cached in memory, and then the subsequent request context of all the other remove the cached result from memory to call the dependency on it.

In this case, the benefit is not repeated in the context of a request many times the same command, the implementation of network requests to avoid duplication, improve the performance of the entire request.

For chestnuts. For instance, we in the context of a request, the request for the data acquisition productId 1, the cache is not the first time, you will get data from the goods and services, the result returns the latest data, while the data cached in memory. Subsequent same request context, if there is a request for data acquisition productId 1, taken directly from the cache like.
Here Insert Picture Description
HystrixCommand and HystrixObservableCommand can specify a cache key, then Hystrix will be cached automatically, and then in the same request context, again accessed, it would direct access to the cache.

Here, we combine a specific business scenarios, take a look at how to use the request cache request caching technology. Of course, the following code only as a basic Demo only.
Now, suppose we have to do a bulk query interface product data, which in this, we use HystrixCommanda one-time batch query data from multiple product id. But there is a problem, if Nginx in the local cache fails to reacquire the number of cache, passing over productIds are no de-emphasis, such as productIds = 1,1,1,2,2, you might say, item id there have been repeated, according to our previous business logic might be repeated three times for productId = 1 query commodities, commodity query twice productId = 2.
Our product data for batch query interface, you can do with a request cache optimization, that the first request is a request context, for the same commodity query is executed only once, and the rest are gone duplicate request cache.

Hystrix achieve registration request context and filter

HystrixRequestContextFilter defined class that implements the interface Filter.

/**
 * Hystrix 请求上下文过滤器
 */
public class HystrixRequestContextFilter implements Filter {
@Override
    public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) {
        HystrixRequestContext context = HystrixRequestContext.initializeContext();
        try {
            filterChain.doFilter(servletRequest, servletResponse);
        } catch (IOException | ServletException e) {
            e.printStackTrace();
        } finally {
            context.shutdown();
        }
    }
@Override
    public void destroy() {
}
}

The filter is then subject to registration SpringBoot Applicationin.

@SpringBootApplication
public class EshopApplication {
public static void main(String[] args) {
        SpringApplication.run(EshopApplication.class, args);
    }
@Bean
    public FilterRegistrationBean filterRegistrationBean() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new HystrixRequestContextFilter());
        filterRegistrationBean.addUrlPatterns("/*");
        return filterRegistrationBean;
    }
}

command override getCacheKey()methods
in GetProductInfoCommand, the rewriting getCacheKey()method, this is the case, the results of each request, the request will be placed Hystrix context. The next time a request for the same data for productId, direct access to the cache, no need to call the run () method.

public class GetProductInfoCommand extends HystrixCommand<ProductInfo> {
private Long productId;
private static final HystrixCommandKey KEY = HystrixCommandKey.Factory.asKey("GetProductInfoCommand");
public GetProductInfoCommand(Long productId) {
        super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ProductInfoService"))
                .andCommandKey(KEY));
        this.productId = productId;
    }
@Override
    protected ProductInfo run() {
        String url = "http://localhost:8081/getProductInfo?productId=" + productId;
        String response = HttpClientUtils.sendGetRequest(url);
        System.out.println("调用接口查询商品数据,productId=" + productId);
        return JSONObject.parseObject(response, ProductInfo.class);
    }
/**
     * 每次请求的结果,都会放在Hystrix绑定的请求上下文上
     *
     * @return cacheKey 缓存key
     */
    @Override
    public String getCacheKey() {
        return "product_info_" + productId;
    }
/**
     * 将某个商品id的缓存清空
     *
     * @param productId 商品id
     */
    public static void flushCache(Long productId) {
        HystrixRequestCache.getInstance(KEY,
                HystrixConcurrencyStrategyDefault.getInstance()).clear("product_info_" + productId);
    }
}

Here wrote a flushCache () method we have developed for manually delete the cache.

controller calls the command query product information

In a web request context, incoming goods id list, search hundreds of product data information. For each productId, we have created a command.
If id list does not go heavy, then repeat the id, when the second query will go directly to the cache.

@Controller
public class CacheController {
/**
     * 一次性批量查询多条商品数据的请求
     *
     * @param productIds 以,分隔的商品id列表
     * @return 响应状态
     */
    @RequestMapping("/getProductInfos")
    @ResponseBody
    public String getProductInfos(String productIds) {
        for (String productId : productIds.split(",")) {
            // 对每个productId,都创建一个command
            GetProductInfoCommand getProductInfoCommand = new GetProductInfoCommand(Long.valueOf(productId));
            ProductInfo productInfo = getProductInfoCommand.execute();
            System.out.println("是否是从缓存中取的结果:" + getProductInfoCommand.isResponseFromCache());
        }
return "success";
    }
}

Initiate a request
call interface, query information more items.
http: // localhost:? 8080 /
getProductInfos productIds = 1,1,1,2,2,5 console, we can see the following results.

Call Interface query product data, productId = 1
whether the result is taken from the cache: false
whether the result is taken from the cache: true
whether the result is taken from the cache: true
calling interface to query product data, productId = 2
whether taken from the results cache: false
whether the result is taken from the cache: true
calling interface to query product data, productId = 5
whether to take results from the cache: false

The first query productId=1data query interface calls, not taking the results from the cache. And then again query productId=1request, direct access to the cache, so, obviously much higher efficiency.

Delete the cache
we write a UpdateProductInfoCommand, after updating the product information, written before manually call flushCache(), manually delete the cache.

public class UpdateProductInfoCommand extends HystrixCommand<Boolean> {
private Long productId;
public UpdateProductInfoCommand(Long productId) {
        super(HystrixCommandGroupKey.Factory.asKey("UpdateProductInfoGroup"));
        this.productId = productId;
    }
@Override
    protected Boolean run() throws Exception {
        // 这里执行一次商品信息的更新
        // ...
// 然后清空缓存
        GetProductInfoCommand.flushCache(productId);
        return true;
    }
}

In this way, after the queries of the goods, the first call will go to the interface for the latest product information.

Guess you like

Origin blog.csdn.net/baidu_26954625/article/details/90634269