JAVASpring

杂谈:Springboot可以同时处理多少请求?

SpringBoot能同时处理多少请求

SpringBoot默认的内嵌容器是Tomcat,也就是我们的程序实际上是运行在Tomcat里的。所以与其说SpringBoot可以处理多少请求,到不如说Tomcat可以处理多少请求。

一、并发测试


1.1 代码

SpringBoot可以同时处理多少请求?站在SpringBoot的角度来,确实可以通过一些配置来有效的去控制一次请求的连接数。比如控制100,一旦连接数超过100,客户端就会显示连接超时。看一个简单的例子,我在这里创建了一个Springboot应用,声明了一个接口。里面很简单,就是sleep了两秒。

@Slf4j
@RestController
@RequestMapping("test")
public class TestController {
 
    @GetMapping
    public String test() throws InterruptedException {
        log.info("线程:{}", Thread.currentThread().getName());
        Thread.sleep(2000);
        return "OK";
    }
}

然后我配置了连接池的一些参数,参数的意思呢,后面会讲到。

server:
  tomcat:
    threads:
      min-spare: 10        # 最少线程数
      max: 20              # 最多线程数
    max-connections: 30    # 最大线程数
    accept-count: 10       # 最大等待数

1.2 压测

然后通过JMeter来给大家做一个压测。我发起的线程数是100,qps相当于是100,请求我们刚刚的那个接口。可以看到此时的这个异常数是60%,也就是我们的100请求当中呢,只有40次成功了,其中60次是失败的。结合刚刚这个参数来看一下,最大连接数加这个最大等待数的数量,40次成功了,剩下的60次呢是失败了。

二、参数说明


作为SpringBoot,我可以通过配置内嵌的这个tomcat的线程池的参数去控制它的请求数量,当我们问到SpringBoot可以同时处理多少请求的话,我们只需要知道这两个参数它的默认值是多少,其实就是这个问题的答案了。

这几个参数的默认值呢,我们打开这个spring配置原数据的json文件来进行查看,这份文件当中把SpringBoot所有的默认可配置项,都给我们列出来了。包括每一个配置项,它的说明、默认值都在上面。我们刚刚配置的这个最大连接数max-connections,它的默认值是8192,最大等待数是100,所以SpringBoot可以同时处理多少请求的答案呢,就是8192+100=8292。

三、详解


那在我们的一个高并发的应用当中,这几个参数它需不需要改变呢?答案是肯定需要的。首先要搞清楚这几个参数的意思,才能更好的去配置。

大家可以把我们的web服务器,当做是一个饭店,最小线程数当做饭店里面正式员工的厨师,最大线程数当做兼职厨师,最大连接数是我们这个饭店最多可以容纳的客户,最大等待数当作是最多可以多少人去排队。

大概的流程是这样的。当一个客户进来,我们首先会看一下这个最大连接数,是不是小于当前连接数,也就是这个饭店里面到底能不能坐得下。如果能坐下的话,我们看一下最小工作线程数里面,这两个厨师他是不是都闲着,如果都闲着的话,肯定就分配一个厨师去直接给我们炒菜了。那如果这两个厨师,他都在为这两桌客人在炒菜的话,那我们就需要去找到那些兼职的厨师来为我们去炒菜。炒完菜,整个流程就结束了。

像我们刚刚应用程序当中所示,我们的最大连接数呢配置的是30,最大等待数是10,最大工作线程数是20,最小工作线程数是10,然后我们的连接我们的qps是100,那这个过程是什么样的呢?那首先这100个请求进来,我们会看一下最大连接数当中是不是有,我们会分配30个人坐到饭店里面去,然后呢还有10个人可以去排队。那么其余的60个人他不会立马走,会观望一下,看还有没有机会,所以这60个人会等待一个超时时间,如果在这个超时间之内,你这40个人有人出来,有人吃完了之后,我这60个人依然可以进去。如果这60个人耐心用光了,也就是我的超时时间用完了,就会显示connect timeout,连接超时大概是一个这样的过程。

这30个人进来之后,并不是说直接就有30个线程直接去处理,而是根据最大工作线程数来的。首先看一下最小线程数能不能满足,如果最小线程数满足的话,就不需要额外再开辟多余的线程去处理了。如果最小线程数满足不了,就需要开辟多余的线程数来去帮我们炒菜。最大线程数我们配置是20个,那这30个呢首先会有20个来进行处理,其余的10个会放入到我们线程池的阻塞队列当中,完了之后再处理这10个,最后处理排队的这10个。如果这60个没有超过这个连接超时时间的话,那这60个依然会进行处理。

那我们刚刚压测的时候,为什么这60个都失败了呢?其实是因为我也配置了一个连接超时间是300ms,那我们的业务处理时间是2秒钟,所以其余的60个肯定就超时了。我只能等待300ms,我的耐心就300ms,你如果这里面还没人出来,我就直接走了。

实际我们在服务器当中,要去调整这几个参数的话,得结合很多的指标,比如说我们服务器的硬件的性能,io模型,网络,还要结合一些压测,服务器的监控,实际的数据,才能设置最佳性能的一个配置。