High concurrency scenarios - Merge Request (b) using the Secret HystrixCollapser- Queue Thread Pool and asynchronous implementation

background

After a highly concurrent Internet scenario, the request will be very much, but the database connection pool is relatively small, or the need to reduce CPU pressure to reduce the processing logic, it is necessary to a single query, by some means, to a plurality of batch query returns . Such as: Alipay, the query "personal information", the user will only trigger a request, check their information, but more than one person at the same time to do so will result in multiple database connections. In order to reduce the connection, the server needs to be performed JAVA merge request, the plurality of "personal information" query interface, combined into a plurality of batch query "personal information" interface, and personal information as a Key id returned to the upstream system or database page URL, etc. caller.

purpose

  1. Reduce the number of database access
  2. A plurality of requests per unit time, is a combined request. Let the business logic to a single sql queries instead sql batch queries. Or logic inside need to call redis, batch logic that can be used inside pipeline redis to achieve.
  3. The need to use JDK primary means to achieve the merger request, because we do not necessarily have Hystrix, is achieved by the native way, and to resolve HystrixCollapser which is how to achieve.

The main means of settlement

  1. SpringCloud of Hystrix custom HystrixCollapse and HystrixCommand
  2. SpringCloud way of Hystrix comment.
  3. When no service governance framework, using the JDK queue, scheduled tasks thread pool.

In the last chapter has been said of the first two kinds, in view of the students have no SpringCloud, so use the first three kinds of requests to do the merge, and analyze the request with the principle of consolidation.

Chapter recommended to walk, corresponding to the second chapter describes the internal principles HystrixCollapser high concurrency scenarios - Request combining (a) SpringCloud the combined request Hystrix

Interactive process

The request to join -SpringCloud (1) .png

Develop

This section using the native JDK development package, so there is no SpringCloud so many things you want to configure, write code only one class.

1. Create a layer request

Only a single query needs to be exposed interfaces, business logic in doing request merge logic.

@RestController
public class UserController {
    @Autowired
    private UserBatchWithFutureServiceImpl userBatchWithFutureServiceImpl;
   @RequestMapping(method = RequestMethod.GET,value = "/userbyMergeWithFuture/{id}")
    public User userbyMergeWithFuture(@PathVariable Long id) throws InterruptedException, ExecutionException {
        User user = this.userBatchWithFutureServiceImpl.getUserById(id);
        return user;
    }
}
复制代码

2. Request layers merge logic

  1. Merge logic creation request entry
  2. Create a blocked queue for accumulating a plurality of request parameters
  3. Creating CompletableFuture class, thread blocking order under this section, such as batch queries dealt with, asynchronous obtain information about the current User id corresponding result.
  4. CompletableFuture.get method waits to perform asynchronous result notification.
@Component
public class UserBatchWithFutureServiceImpl {
    /** 积攒请求的阻塞队列 */
    private LinkedBlockingDeque<UserQueryDto> requestQueue = new LinkedBlockingDeque<>();

    public User getUserById(Long id) throws InterruptedException, ExecutionException {

        UserQueryDto userQueryDto = new UserQueryDto();
        userQueryDto.setId(id);
        CompletableFuture<User> completedFuture = new CompletableFuture<>();
        userQueryDto.setCompletedFuture(completedFuture);

        requestQueue.add(userQueryDto);

        User user = completedFuture.get();
        return user;
    }

复制代码

HystrixCollapser also use this approach means asynchronous notification to do so before the request interface main thread blocked waiting to get real results.

3. regular tasks

Scheduled task created in the same class, so that Bean using @PostConstruct configuration of the current class after performing the method, generating a 5-second timer task. We can set the timing of the time, I was more convenient for testing, but with 5 seconds.

    /** 线程池数量 */
    private int threadNum = 1;
    /** 定时间隔时长 */
    private long period = 5000;
    @PostConstruct
    public void init() {
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(createDeviceMergeNum);
        // 每5秒执行一次
        scheduledExecutorService.scheduleAtFixedRate(new UserBatchThread(), 0, createDeviceMergePeriod,
                TimeUnit.MILLISECONDS);
    }
复制代码

HystrixCollapser every n milliseconds will perform a single method of processing a batch process turn, is achieved by such.

4. Create an inner class class at UserBatchWithFutureServiceImpl

To create an internal timer based logic to perform this task, and in order to clean the code, a large coding block is not in the method of creating a thread pool.

Inside the main logic within the class:

  1. RequestQueue queue holds requests from the interface parameters, the acquisition of all members, and when placed in a local variable in this task logic triggers
  2. And withdrawing the key request id parameter into a local variable List.
  3. Simply get out of variables, batch queries
  4. Finally CompletedFuture asynchronous notification and wake up the thread getUserById method of waiting.
public class UserBatchThread implements Runnable {

        @Override
        public void run() {
            List<UserQueryDto> requestQueueTmp = new ArrayList<>();
            // 存放批量查询的入参
            List<Long> requestId = new ArrayList<>();

            // 把出请求层放入的消息queue的元素取出来
            int size = requestQueue.size();
            for (int i = 0; i < size; i++) {
                UserQueryDto request = requestQueue.poll();
                if (Objects.nonNull(request)) {
                    requestQueueTmp.add(request);
                    requestId.add(request.getId());
                }
            }

            if (!requestId.isEmpty()) {
                try {
                    List<User> response = getUserBatchById(requestId);
                    Map<Long, User> collect = response.stream().collect(
                            Collectors.toMap(detail -> detail.getId(), Function.identity(), (key1, key2) -> key2));
                    // 通知请求的线程
                    for (UserQueryDto request : requestQueueTmp) {
                        request.getCompletedFuture().complete(collect.get(request.getId()));
                    }

                } catch (Exception e) {
                    // 通知请求的线程-异常
                    requestQueueTmp.forEach(request -> request.getCompletedFuture().obtrudeException(e));
                }
            }
        }

    }

    public List<User> getUserBatchById(List<Long> ids) {
        System.out.println("进入批量处理方法" + ids);
        List<User> ps = new ArrayList<>();
        for (Long id : ids) {
            User p = new User();
            p.setId(id);
            p.setUsername("dizang" + id);
            ps.add(p);
        }
        return ps;
    }
复制代码

Request element in the queue of the interface, here will be removed, HystrixCollasper poll is using this method of obtaining atomic queue elements which will not be repeated a plurality of times trigger timing acquisition task, as long as there is at least one will do batch query, so when a merge request HystrixCollasper, even if only a request for n msec, the processing will go.

Testing and certification

  1. As with the previous chapter trigger Swagger-ui page
  2. Two different request parameters
  3. The results in the figure below, console log request has been output into the two parameters

output.png

to sum up

Here I believe we have completed the merger requests. This is not dependent on the frame, based on the original approach, using a queue stored query into the desired parameters, then using the thread pool periodically acquired reference into the queue, then batch process, using a thread made asynchronously Future return results. So that we understand the internal processes of the HystrixCollasper of SpringCloud. We are hoping to help the project without a frame, or the students in the case of the company's technology stack inappropriate.

Text Demo

I springcloud in the demo inside, look at the content provider-hystrix-request-merge this project, in UserBatchWithFutureServiceImpl class.

gitee.com/kelvin-cai/…


Welcome attention to public numbers, the article step faster

My public number: Jizo thinking

Nuggets: possession of Kelvin

Jane book: possession of Kelvin

My Gitee: Jizo Kelvin gitee.com/kelvin-cai

Guess you like

Origin juejin.im/post/5e7da390f265da79a16d9a56