目录
一、示例代码
java
@RestController
@Slf4j
public class RequestController {
@GetMapping("/test")
public String test(HttpServletRequest request) throws Exception{
log.info("线程:{}",Thread.currentThread().getName());
Thread.sleep(2000);
return "success";
}
}
配置连接池配置
java
server:
tomcat:
threads:
# 最少线程数
min-spare: 10
# 最多线程数
max: 20
# 最大连接数
max-connections: 20
# 最大等待数
accept-count: 10
然后通过Jmeter进行压测
设置100个线程
请求接口
我们看到异常率是60%,意思就是100个请求,有60个报错,40个访问成功,这个40是我们设置的内嵌的Tomcat中最大连接数和最大等待数的和等于40;
二、那么springboot可以处理多少请求?
即相当于问max-connections
和accept-count
这两个值的默认值是多少
可以打开spring-configuration-metadata.json
文件,里面记录了springboot配置默认值
文件目录:spring-boot-autoconfigure\2.6.13\spring-boot-autoconfigure-2.6.13.jar!\META-INF
线程池常用4大参数
json
{
"name": "server.tomcat.threads.min-spare",
"type": "java.lang.Integer",
"description": "Minimum amount of worker threads.",
"sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties$Tomcat$Threads",
"defaultValue": 10
},
{
"name": "server.tomcat.threads.max",
"type": "java.lang.Integer",
"description": "Maximum amount of worker threads.",
"sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties$Tomcat$Threads",
"defaultValue": 200
},
{
"name": "server.tomcat.max-connections",
"type": "java.lang.Integer",
"description": "Maximum number of connections that the server accepts and processes at any given time. Once the limit has been reached, the operating system may still accept connections based on the \"acceptCount\" property.",
"sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties$Tomcat",
"defaultValue": 8192
},
{
"name": "server.tomcat.accept-count",
"type": "java.lang.Integer",
"description": "Maximum queue length for incoming connection requests when all possible request processing threads are in use.",
"sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties$Tomcat",
"defaultValue": 100
}
-
min-spare :最小线程数
最小工作空闲线程数,默认10,适当增大一些,以便对应突然增长的访问量
-
max-threads : 最大线程数
每一次Http请求到达Web服务,tomcat都会创建一个线程来处理该请求,那么最大线程数决定了web服务容器可以同时处理多少个请求。 maxThreads默认值200, 肯定建议增加,但是增加线程是有成本的,更多的线程不仅仅会带来更多的线程上下文切换成本,而且意味着带来更多的内存消耗。JVM默认的情况下在创建新线程时会分配大小为1M的线程栈,所以更多的线程意味着需要更多的内存,线程数的经验值为 1C2G内存为200,线程数经验值为200; 4C8G线程数经验值为800
-
maxConnections:最大连接数
这个参数是指在同一时间,tomcat能够接受的最大连接数。对于Java的阻塞式BIO,默认值是maxthreads的值;如果在BIO模式使用定制的Executor执行器,默认值将是执行器中maxthreads的值。对于Java 新的NIO模式,maxConnections 默认值是10000。
对于windows上APR/native IO模式,
maxConnections默认值为8192
,这是出于性能原因,如果配置的值不是1024的倍数,maxConnections 的实际值将减少到1024的最大倍数。如果设置为-1,则禁用maxconnections功能,表示不限制tomcat容器的连接数。
maxConnections和accept-count的关系为:当连接数达到最大值maxConnections后,系统会继续接收连接,但不会超过acceptCount的值
-
accept-count : 最大等待数
当所有的请求处理线程都在使用时,所能接收的连接请求的队列最大长度。当队列已满时,任何的连接请求都将被拒绝。 accept-count 默认值100 。详细来说,当调用http请求数达到tomcat的最大线程数时,还有新的http请求到来,这时tomcat会将该请求放在等待队列中,
这个acceptCount就是能够接收的最大等待数,默认100
。如果等待队列也被放满了,这个时候再来新的请求的请求就会被tomcat拒绝(connection refused)
springboot最多可以处理多少请求呢?就是8192+100 = 8292
三、maxConnections、maxThreads、acceptCount的关系
我们可以把tomact比做一个饭店,流程是取号、入座、叫服务员可以做三个形象的类比
(1)thread.min-spare 最小线程数
可以类比为厨师的核心个数,同一个时刻只能给一张餐桌炒菜,就像极了JVM中的一条线程
(2) maxThreads 最大线程数
可以类比为厨师的最大个数
(3) maxConnections 最大连接数
可以类比为饭店的餐桌数量,如果所有的桌子都已坐满了,则表示餐厅已满,已经达到服务的数量上限,不能再有顾客进入餐厅了
(4) acceptCount 最大等待数
可以类比餐厅的排号处能够容纳排号的最大数量。排号的数量不是无限制的,餐厅的排号到了一个数量之后,服务往往会说:已经可以客满
整个流程大致如下:
- 取号: 如果maxConnentions连接数没有满,就不需要取号,因为还有空余的餐桌,直接被大堂服务员领上餐桌,点菜就餐就可。如果macConnections 连接数满了,但是取号人数没有达到acceptCount 则取号成功。如果取号人数达到acceptCount,则拿号失败,会得到tomcat的 connection refused connect 的回复信息
- 上桌:如果有餐桌空出来了,表示maxConnections连接数没有满,排除的人可以进入大堂就餐
- 就餐:就餐需要厨师炒菜。厨师的数量比顾客的数量肯定会少一些。一个厨师一个需要给多张餐桌炒菜,如果就餐的人越多,厨师也会忙不过来。这时候就可以增加厨师,一旦增加到maxThreads的值,如果还是不够,只能拖慢每一张餐桌的上菜速度,这种情况就是大家常见的 "上一道菜吃完了,下一道菜还有没上的" 的尴尬场景
前面配置中,最小工作工作线程数(thread.min-spare)是10,最大工作线程数( maxThreads)是20,最大连接数(maxConnections)是30,最大队列数(acceptCount)是10,QPS是100,其中30会进入最大连接数,10会进入最大队列,其他60会等待超时时间,如果超市时间内,有线程吃完饭,则60个线程还是可以进去,最小线程数10不满足,需要开辟新的工作线程来帮助我们炒菜。