Interface request merging skills, once used, the efficiency will be doubled!

198c664b1060e4ca60779f cac5c5ede5.jpeg

The path to growth as a programmer

Internet/Programmer/Technology/Data Sharing

focus on

This article should take approximately 3.5 minutes to read.

From: blog.csdn.net/leilei1366615/article/details/123858619

1. What is request merge

In WEB projects, we generally use HTTP protocol to handle requests

Then the way we interact with the server will be like this, one request, one processing

248a404624d44f20a61810e2ee9e2420.png

We all know that calling batch interfaces has greater performance advantages than calling non-batch interfaces (because it reduces IO interactions). In high concurrency situations, if very frequent interface requests occur, we can consider request merging. , multiple requests will be delayed for a certain amount of time, and when the cumulative number of requests reaches a certain level, batch requests will be processed.

2. Advantages and disadvantages of request merging

The so-called request merging means merging multiple requests into one batch request.

e44887ad26870e2f2968c54bd1375680.png

advantage:

Wait for a certain period of time or number of requests to process multiple requests, merge them into one request, and reduce IO interaction.

shortcoming:

Since the request needs to wait for a specified time or a specified number of requests, there is a delay in the merged interface, so there are restrictions on the interface that requests the merge. This interface cannot have requirements on response timeliness and supports a certain time delay.

3. Implementation of request merging technology

Use the scheduled thread pool ScheduledExecutorService and the memory queue LinkedBlockingDeque to implement request merging

?

The principle is to cache user requests. When the number of cached requests reaches the specified number or reaches the scheduled thread pool execution, multiple single request processing will be merged into multi-processing, and the batch interface will be called for operation.

?

rely

  • Only JDK is required, no third-party dependencies are required

The batch request merging tool class is defined as follows:

The core principle is to put the request into the queue, detect whether the number of memory queues exceeds the set threshold, and trigger the scheduled thread pool execution when the time threshold expires.

package com.leilei.support;

import lombok.extern.log4j.Log4j2;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

/**
 * @author lei
 * @desc Request to merge tool classes
 **/
@Log4j2
public class BatchCollapser<T, R> {
    private static final Map<Class, BatchCollapser> BATCH_INSTANCE =new ConcurrentHashMap<>();
    private static final ScheduledExecutorService SCHEDULE_EXECUTOR = Executors.newScheduledThreadPool(1);

    private final LinkedBlockingDeque<T> batchContainer = new LinkedBlockingDeque<>();
    private final BatchHandler<List<T>, R> handler;
    private final int countThreshold;

    /**
     * constructor
     *
     * @param handler processor
     * @param countThreshold quantity threshold, the processor is triggered after reaching this threshold
     * @param timeThreshold time threshold, the processor is triggered after reaching this time
     */
    private BatchCollapser(BatchHandler<List<T>, R> handler, int countThreshold, long timeThreshold) {
        this.handler = handler;
        this.countThreshold = countThreshold;
        SCHEDULE_EXECUTOR.scheduleAtFixedRate(() -> {
            try {
                this.popUpAndHandler(BatchHandlerType.BATCH_HANDLER_TYPE_TIME);
            } catch (Exception e) {
                log.error("pop-up container exception", e);
            }
        }, timeThreshold, timeThreshold, TimeUnit.SECONDS);
    }

    /**
     * Add request elements to the queue
     * @param event
     */
    public void addRequestParam(T event) {
        batchContainer.add(event);
        if (batchContainer.size() >= countThreshold) {
            popUpAndHandler(BatchHandlerType.BATCH_HANDLER_TYPE_DATA);
        }
    }

    /**
     * Get requests from the queue and process them in batches
     * @param handlerType
     */
    private void popUpAndHandler(BatchHandlerType handlerType) {
        List<T> tryHandlerList = Collections.synchronizedList(new ArrayList<>(countThreshold));
        batchContainer.drainTo(tryHandlerList, countThreshold);
        if (tryHandlerList.size() < 1) {
            return;
        }

        try {
            R handle = handler.handle(tryHandlerList, handlerType);
            log.info("Batch processing tool execution result:{}", handle);
        } catch (Exception e) {
            log.error("batch execute error, transferList:{}", tryHandlerList, e);
        }
    }

    /**
     * Get the combiner instance
     *
     * @param batchHandler processing executor
     * @param countThreshold threshold number (number of queues)
     * @param timeThreshold threshold time in seconds (the current setting is to obtain the threshold number of requests after triggering, which can be modified as needed)
     * @param <E>
     * @param <R>
     * @return
     */
    public static <E, R> BatchCollapser<E, R> getInstance(BatchHandler<List<E>, R> batchHandler, int countThreshold, long timeThreshold) {
        Class jobClass = batchHandler.getClass();
        if (BATCH_INSTANCE.get(jobClass) == null) {
            synchronized (BatchCollapser.class) {
                BATCH_INSTANCE.putIfAbsent(jobClass, new BatchCollapser<>(batchHandler, countThreshold, timeThreshold));
            }
        }
        return BATCH_INSTANCE.get(jobClass);
    }

    /**
     * Request processing interface
     *
     * @param <T>
     * @param <R>
     */
    public interface BatchHandler<T, R> {
        /**
         * Handle user specific requests
         *
         * @param input
         * @param handlerType
         * @return
         */
        R handle(T input, BatchHandlerType handlerType);
    }

    /**
     * Merge execution type enumeration
     */
    public enum BatchHandlerType {
        /**
         * Quantity type
         */
        BATCH_HANDLER_TYPE_DATA,

        /**
         * Time type
         */
        BATCH_HANDLER_TYPE_TIME,
    }
}

How to use it:

package com.leilei.support;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.List;

/**
 * @author lei
 * @desc
 **/
@Service
public class ProductService implements BatchCollapser.BatchHandler<List<Integer>, Integer> {
    private BatchCollapser<Integer, Integer> batchCollapser;

    @PostConstruct
    private void postConstructorInit() {
        // When the number of requests reaches 20, or the requests are merged and executed every 5 seconds
        batchCollapser = BatchCollapser.getInstance(ProductService.this, 20, 5);
    }

    @Override
    public Integer handle(List<Integer> input, BatchCollapser.BatchHandlerType handlerType) {
        System.out.println("Processing type:" + handlerType + ", received batch request parameters: " + input);
        return input.stream().mapToInt(x -> x).sum();
    }


    /**
     * Assume I have a request of 300ms here
     */
    @Scheduled(fixedDelay = 300)
    public void aaa() {
        Integer requestParam = (int) (Math.random() * 100) + 1;
        batchCollapser.addRequestParam(requestParam);
        System.out.println("Current request parameters:" + requestParam);

    }
}
@Data
public class Product {
    private Integer id;
    private String notes;
}

bac59fa610aa421393d9ae7464939367.png

Of course, the above tools are just DEMO. You can improve them by yourself, weigh the pros and cons of request merging, and reduce the pressure on the server during high concurrent requests.

Recommended reading:

Transitioning from RestTemplate to WebClient in SpringBoot: A Detailed Guide

Ignoring logs will lead to big losses. Let me teach you how to use SpringBoot logs step by step!

Interview questions for junior high school and senior Internet companies (9 Gs)
The content includes Java basics, JavaWeb, MySQL performance optimization, JVM, locks, millions of concurrency, message queues, high-performance caching, reflection, Spring family bucket principles, microservices, Zookeeper... and other technology stacks!
?Click to read the original text to get it! I have read it