[Microservice Notes 08] Hystrix of Microservice Components Realizes Request Merging Function

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

Table of contents

1. Hystrix request merge

1.1. What is request merge

1.2. Implementation of request merging

(1) Introduce dependencies

(2) Write a service provider

(3) Consumer (Service layer code)

(4) Consumer (Controller layer code)

(5) Test request merge


1. Hystrix request merge

1.1. What is request merge

The calls between microservices and microservices all need to establish a communication connection. Take the HTTP interface as an example. Every communication needs to establish and disconnect the connection. If the calls between microservices are very frequent, it will There are many connections being established and disconnected. In order to reduce the number of requested connections, Hystrix proposes the function of request merging.

Request merging, that is, merging multiple identical requests into one request, and then only calling the interface once to obtain all the data. After the data is obtained, the data needs to be distributed to the request before the merging, so that each request can Can normally get the return result that belongs to me.

When request merging is enabled, Hystrix will merge those same URI requests into one request, and then call the microservice interface. From here, you can see that after the request is merged, the interface that was originally called multiple times is now only An interface call is required, which reduces a lot of request connections, which can also improve the high availability of the system.

To achieve request merging, the downstream system must support the batch processing interface, because the original single-call interface, the result of request merging is equivalent to putting the request parameters of multiple interfaces into one interface, so the downstream system must be able to support batch processing Handle data queries with multiple request parameters.

The use of request merging, generally speaking, is for the interface of the query class, which is equivalent to the downstream system supporting the batch query function. At this point, do you want to ask, since the downstream system supports batch query, shouldn’t it be enough for me to directly call the batch query interface? ? ?

  • First of all, you have to understand that if you are a user-initiated interface, you can directly call the batch processing interface, which is indeed possible.
  • But in the Internet, there are many users in an application system, and each user may call the same interface to query different data. At this time, request merging will work.

To achieve request merging, you can use the [@HystrixCollapser] annotation and the [@HystrixCommand] annotation. @HystrixCollapser annotation: Specifying a method requires enabling the request merging function. @HystrixCommand annotation: Mark a method as a Hystrix command.

1.2. Implementation of request merging

(1) Introduce dependencies

  • On the service consumer side, introduce the hystrix dependency.
<!--hystrix 依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

(2) Write a service provider

As mentioned above, in order to realize the request merging function, the downstream system must provide a batch processing interface, so here, the service provider needs to provide a batch query interface.

package com.gitcode.hystrix.controller;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

/**
 * @version 1.0.0
 * @Date: 2023/4/9 10:11
 * @Copyright (C) ZhuYouBin
 * @Description: hystrix 请求合并
 */
@RestController
@RequestMapping("/hystrix/provider")
public class CollapseController {

    /**
     * 根据id批量查询
     */
    @PostMapping("/hystrixCollapse")
    public List<String> hystrixCollapse(@RequestBody List<String> ids) {
        List<String> ans = new ArrayList<>();
        // 这里模拟批处理的过程
        ids.forEach(key -> {
            ans.add("这是key=" + key + "的响应结果.");
        });
        return ans;
    }
    
}

(3) Consumer (Service layer code)

  • In the consumer's Service service layer, we need to use the [@HystrixCollapser] annotation and [@HystrixCommand] annotation to declare the method that needs to implement request merging.
  • 【@HystrixCollapser】Note: Used on methods that need to enable request merging.
  • [@HystrixCommand] annotation: used on the interface method that performs batch processing after the request is merged.
package com.gitcode.hystrix.service;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCollapser;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.List;
import java.util.concurrent.Future;

/**
 * @version 1.0.0
 * @Date: 2023/4/9 10:16
 * @Copyright (C) ZhuYouBin
 * @Description: Hystrix 请求合并
 */
@Service
public class HystrixCollapseService {

    @Autowired
    private RestTemplate restTemplate;

    /**
     * 根据ID查询
     */
    @HystrixCollapser(collapserKey = "请求合并的唯一key",
            // 作用域: 这里设置成全局的
            scope = com.netflix.hystrix.HystrixCollapser.Scope.GLOBAL,
            // 批处理方法: 当请求合并之后, hystrix 会调用这个批处理方法发起接口的调用【这个方法是自己写的】
            batchMethod = "batchQueryData",
            // 请求合并的属性: 满足什么条件才进行请求合并
            collapserProperties = {
                    // 定义属性
                    // timerDelayInMilliseconds: 在指定时间内的所有相同请求,都将被请求合并, 单位毫秒, 默认10ms
                    // 200 毫秒内的请求将全部被合并
                    @HystrixProperty(name = "timerDelayInMilliseconds", value = "5000"),
                    // maxRequestsInBatch: 请求合并最大的请求数量,当到达这个数量之后,就会执行一次请求合并
                    @HystrixProperty(name = "maxRequestsInBatch", value = "4"),
            }
    )
    // TODO 需要注意的是,请求合并的方法返回值必须是:Future 类型
    public Future<String> queryById(String id) {
        // 这个方法没啥作用了,所以不需要方法体,因为单个请求都将合并,之后统一的调用批处理方法
        System.out.println("调用queryById方法......");
        return null;
    }

    /**
     * 请求合并之后的批处理方法
     */
    @HystrixCommand
    private List<String> batchQueryData(List<String> ids) {
        // 在这里实现批量请求的调用
        String url = "http://127.0.0.1:5678/hystrix/provider/hystrixCollapse";
        final List<String> list = restTemplate.postForObject(url, ids, List.class);
        System.out.println("调用batchQueryData批处理接口......");
        return list;
    }

}
  • PS: Here is a question, how does Hystrix know which data should be the response result of which requests in the batch interface.

(4) Consumer (Controller layer code)

In the controller control layer, we only need to call the queryById() method of the Service layer to query data. Since this method is a Future type, we can get the return value by calling the [Future.get()] method. Note that Yes: the get() method is blocked, the return value is not ready, and it will always be in a blocked waiting state.

package com.gitcode.hystrix.controller;

import com.gitcode.hystrix.service.HystrixCollapseService;
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;

import java.security.SecureRandom;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

/**
 * @version 1.0.0
 * @Date: 2023/4/9 10:16
 * @Copyright (C) ZhuYouBin
 * @Description:
 */
@RestController
@RequestMapping("/hystrix/consumer")
public class CollapseController {

    @Autowired
    private HystrixCollapseService hystrixCollapseService;

    @GetMapping("/requestCollapse")
    public String requestCollapse() throws ExecutionException, InterruptedException {
        String id = new SecureRandom().nextInt() + "";
        final Future<String> future = hystrixCollapseService.queryById(id);
        // 获取方法的返回值,阻塞等待
        final String result = future.get();
        System.out.println("返回值: " + result);
        return "success,接口返回值是: " + result;
    }
}

(5) Test request merge

Start the eureka registration center, consumer service consumer, and provider service provider projects in turn. I use jemeter to test concurrent requests. Of course, you can also directly refresh the access interface multiple times in the browser for testing.

After calling the interface, check the console input log:

At this point, Hystrix's implementation of request merging is introduced.

In summary, this article is over, mainly introducing the Hystrix of microservice components to implement the function of request merging.

Guess you like

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