We all know that the default embedded container of SpringBoot is Tomcat, which means that our program actually runs in Tomcat. So it's not so much how many requests SpringBoot can handle, but how many requests Tomcat can handle.
The default configuration of Tomcat is in the spring-configuration-metadata.json
file, and the corresponding configuration class is org.springframework.boot.autoconfigure.web.ServerProperties
.
There are four parameters related to the number of requests processed:
server.tomcat.threads.min-spare: The minimum number of worker threads, the default size is 10. This parameter is equivalent to a long-term worker. If the number of concurrent requests does not reach 10, these threads will be used in sequence to process the requests. server.tomcat.threads.max: The maximum number of worker threads, the default size is 200. This parameter is equivalent to a temporary worker. If the number of concurrent requests is between 10 and 200, these temporary worker threads will be used for processing. server.tomcat.max-connections: The maximum number of connections, the default size is 8192. Indicates the maximum number of requests that Tomcat can handle. Requests exceeding 8192 will be placed in the waiting queue.
server.tomcat.accept-count: The length of the waiting queue, the default size is 100.
Give an example to illustrate the relationship between these parameters:
If you compare Tomcat to a restaurant, Then a request is actually equivalent to a guest. min-spare is the chef (permanent workers); max is the total number of chefs (permanent workers and temporary workers); max-connections is the number of seats in the restaurant; accept-count is the number of small benches at the door. Guests who come are given priority to sit in the restaurant, and then the chef starts to work. If the long-term worker can finish the job, let the long-term worker do it. If the long-term worker cannot finish the job, let the temporary worker do it. There are 15 chefs in the picture, and there are 30 seats in the restaurant. That is to say, if 20 guests come now, there will be 5 people waiting in the restaurant first. If 35 people come now and there is no room in the restaurant, 5 people will be asked to sit at the door first. If 50 people come, then there are 40 seats and small benches at the entrance of the hotel, so 10 people will leave.
In other words, the maximum number of requests that SpringBoot can handle at the same time is max-connections accept-count
. Requests exceeding this number will be discarded directly.
I only know that this matter must be carried out in detail.
The above are just theoretical results. Now let’s use a small practical example to demonstrate whether this is the case:
Create a SpringBoot project and configure these in application.yml parameters, because the default number is too large and difficult to test, so set it smaller:
server: tomcat: threads: # 最少线程数 min-spare: 10 # 最多线程数 max: 15 # 最大连接数 max-connections: 30 # 最大等待数 accept-count: 10
Let’s write a simple interface:
@GetMapping("/test") public Response test1(HttpServletRequest request) throws Exception { log.info("ip:{},线程:{}", request.getRemoteAddr(), Thread.currentThread().getName()); Thread.sleep(500); return Response.buildSuccess(); }
The code is very simple, just print the thread name , and then sleep for 0.5 seconds. This will definitely cause some requests to be processed at once and enter the waiting queue.
Then I created a test case using Apifox to simulate 100 requests:
Observe the test results:
As can be seen from the results, since the sum of the set max-connections accept-count is 40, 60 requests will be discarded, which is consistent with our expectations. of. Since the maximum thread is 15, that is, 25 requests will be waited for first, and then 15 will be processed after the first 15 are processed, and finally 10 will be processed, that is, the 40 requests are divided into three batches of 15, 15, and 10. deal with.
#You can see from the console print log that the maximum thread number is 15, which also confirms the previous idea.
To summarize: If the number of concurrent requests is lower than server.tomcat.threads.max, it will be processed immediately, and the excess will be waited first. If If the number exceeds the sum of max-connections and accept-count, the excess will be discarded directly.
So far, we have figured out how many requests SpringBoot can handle at the same time. But here I would like to extend it based on the above example, which is why some values in concurrent scenarios are different from what we expected?
设想有以下场景:厨师们用一个账本记录一共做了多少道菜,每个厨师做完菜都记录一下,每次记录都是将账本上的数字先抄到草稿纸上,计算x+1等于多少,然后将计算的结果写回到账本上。
Spring容器中的Bean默认是单例的,也就是说,处理请求的Controller、Service实例就只有一份。在并发场景下,将cookSum定义为全局变量,是所有线程共享的,当一个线程读到了cookSum=20,然后计算,写回前另一个线程也读到是20,两个线程都加1后写回,最终cookSum就变成了21,但是实际上应该是22,因为加了两次。
private int cookSum = 0; @GetMapping("/test") public Response test1(HttpServletRequest request) throws Exception { // 做菜。。。。。。 cookSum += 1; log.info("做了{}道菜", cookSum); Thread.sleep(500); return Response.buildSuccess(); }
The above is the detailed content of How many requests can SpringBoot handle at the same time?. For more information, please follow other related articles on the PHP Chinese website!