O
O
Oleg Mikhailov2018-09-13 16:16:35
Java
Oleg Mikhailov, 2018-09-13 16:16:35

How to send asynchronous Http requests in Spring without blocking the thread?

Hello!
Need help, maybe someone came across this ... The essence of the problem:
A request comes to the rest controller

method
@RequestMapping(value = "/ssp/test/{place_hash}", method = RequestMethod.GET)
    @ResponseBody
    public DeferredResult<String> test(
        HttpServletRequest servletRequest, HttpServletResponse servletResponse)
        throws Exception {

        DeferredResult<String> output = new DeferredResult<>();
        this.suspendedRequests.add(output);
        output.onCompletion(() -> suspendedRequests.remove(output));
        new Test(servletRequest, servletResponse, sspHandler).setValue(output);

        return output;
    }


And then there should be the following sequence: client request -> processing request data -> mailing to 5 different third-party APIs and waiting for a response from them -> collecting data from this mailing, generating a response -> returning a response to the client
The problem is exactly how to collect it back this data from all 5 answers without delaying the stream for long? Requests have timeouts of 350 ms, but the request itself is executed for almost 2 seconds, which is incredibly long.
I thought to collect ConcurrentLinkedDeque> from them and return responses with callbacks, but it turns out that the thread will still wait until they finish sending requests.

Answer the question

In order to leave comments, you need to log in

3 answer(s)
V
vooft, 2018-09-16
@Olegatorapp

Use non-blocking http client? Like Apache HttpAsyncClient?
If it is not possible to add a reactive library, then collect the results through CompletableFuture and set the value of DeferredResult in the final callback.

K
kidar2, 2018-09-14
@kidar2

Or maybe the client himself will make these 5 requests for third-party services? If this is a web, then the task is easily solved on js. Why do we need an intermediate one?

E
Evhen, 2018-09-15
@EugeneP2

1) Cacheapnie. Do all 5 external services return a unique response each time? Or does the service itself return a unique response each time? - If not, then the answers need to be cached + limit the lifetime of the cache.
2) High timings of external services 5 * 350 = ~ 2000 - these requests need to be parallelized. We create a threadPool for many threads and add Callable tasks to it and, according to the returned Futures, we wait for all the results and return them to the client.
3) increase the maximum number of threads of the container itself (tomcat/jetty) in the configs
4) Start the service on different machines/instances and set up a load balancer, for example, Ribbon from the spring technology stack.
The right advice was given to you by sim3x and Satisfied Life, implementation through a queue and workers, followed by a request for the result by the client by ID. Many banking services operate on this architecture and withstand heavy loads.
​If you are already so critical of the number of threads or you are somehow limited, then you should pay attention to the reactive programming of Spring
WebFlux

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question