Until now, We have been talking about the async server of the Spring Framework. As the scale of the service became be bigger than before, the way of the async has became important. Especially, nowdays, many companies have been making their service more being separated.
As a result, if the specific point which has a long latency in the request exists, the response is delayed because the request has to stand by until that the other tasks are over. With this reason, the usage of the threads is increased, and the service are faced on the thread pool hell.
Even though the improvement to the structure is important, I am going to resolve this problem in the Spring. Using the DeferredResult and ListenableFuture we talked before would be a key to resolve this problem.
At first, why do using the DeferredResult have good performance? Once creating and destroying the threads consume many resources through a context switching, it would lead to a problem with the thread pool hell. Although any people could say that we can make many threads in the beginning in order to solve the problem, this solution would also have been faced with the same problem in the end. However, using the DeferredResult which uses the queue can resolve the problem. Even if a was such as tomcat has one thread of the servlet, because the DeferredResult uses the queue, we can avoid the thread pool hell. For the test, I am going to make a scenario for comparing with Async and Sync.
We have three end-point which consists of a client, a back-end server and remote server. The remote server has a delay of two seconds, and the client has a role which is a general user who requests something to the server. The thing we should note is back-end servers which are Async Server and Sync Server. The results would be different according to the type of the server.
- The code of the client is like below.
line:12CyclicBarrier is an Object which has a role as synchronizing the thread. Its default value I set up is 101, and if CyclicBarrier.await() is called at 101, next code is processed.
line:17,27 .await() is a method for blocking the next code until being called at 101.
line:32 At this code, the process is blocked through ExecutorService which is a worker for multi thread, and if the tasks using ExecutorService are finished, the next code is processed.
- The code of the remote Server is like below
We are going to assume that the remote server is a server for the third-party the back-end server call and has a latency while around two seconds.
line:21 Because this remote server runs in the same project with other code, we should set up the different port which is 8083.
line:22 This is a property for setting up about the servlet thread whose value is two hundred.
- The code of the sync server is like below This is one of the main servers we have to focus on. If some users request api, this server is called, and this requests something to the remote server again.
line:18 Because this remote server runs in the same project with other code, we should set up the different port which is 8081.
line:22 This is very important for test, and which is a property for setting up about the servlet thread which has just one thread. In order to compare with the async server, this is very essential.
- The code of the async server is like below This is also one of the main servers we have to focus on. If some users request api, this server is called, and this requests something to the remote server again. This server is operated using the way to the async. This server consists of the ListenableFuture and DeferredResult.
line:25 Because this remote server runs in the same project with other code, we should set up the different port which is 8082.
line:26 This is very important for test, and which is a property for setting up about the servlet thread which has just one thread. In order to compare with the sync server, this is very essential.
The Result
Let’s guess how both the async server and the sync server operate differently. Basically, the sync server takes way too long time to handle the request because the individual dealing takes 2 sec, and this server runs sequentially. Also, We can guess that the total time of the response is approximately around (2 * 100)sec. However, we would be faced with the different situation in the async server, unlike the sync server. Even though the async server has just one thread for the servlet, the async server has been dealing with the process as the multi threading. The DeferredResult and ListenableFuture are why it makes the server available to the async. If the server is requested from the user, the server using the DeferredResult handles the worker in the deferredresult’s queue without using the thread. Then, the tasks conduct their processor through the listenablefuture, and the result returning from listenablefuture is responded to the client by using DeferredResult.setRestul() which is the method for returning the data in the callback function.(It has the callback function for error, too). So when the async server is compared with @Async which is supported by Spring, how does the performance?
After using the @Async in the sync server, let’s compare both.
The below is a picture about the usage of the threads in the sync server using @Async. When the server was requested, the usage of the thread is increased rapidly.
By the way, if we request the data to async server, we would check out the amazing result. Look at the below picture
Just one more thread is increased in my laptop. instead of increasing the thread, when being requested, because the server queues the request in deferred-result queue, we could avoid increasing the thread. It would make our service much higher performance. Nowadays, single thread has been popular, especially the side of a javascript. Java also has been ready to use single thread. The problems I want to improve remain. Next article, I am going to talk about that.