SpringBoot内嵌Tomcat(默认配置)不能满足并发需求的解决办法

一、起因

在使用jmeter对系统进行性能压测后,发现系统的默认的tomcat配置无法满足高并发的需求
使用pstree -p 端口号 | wc -l 查看进程数,发现默认的线程数和满载的线程数过少,可以通过修改内嵌tomcat配置来增加工作线程数量

1.具体操作

通过查看spring-configuration-metadata.json中默认配置,可以看到SpringBoot默认的tomcat容器配置如下:

{
      "sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties$Tomcat",
      "defaultValue": 100,
      "name": "server.tomcat.accept-count",
      "description": "Maximum queue length for incoming connection requests when all possible request processing threads are in use.",
      "type": "java.lang.Integer"
}
{
      "sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties$Tomcat",
      "defaultValue": 10000,
      "name": "server.tomcat.max-connections",
      "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.",
      "type": "java.lang.Integer"
}
{
      "sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties$Tomcat",
      "defaultValue": 200,
      "name": "server.tomcat.max-threads",
      "description": "Maximum number of worker threads.",
      "type": "java.lang.Integer"
},
{
      "sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties$Tomcat",
      "defaultValue": 10,
      "name": "server.tomcat.min-spare-threads",
      "description": "Minimum number of worker threads.",
      "type": "java.lang.Integer"
}
  • accept-count:等待队列长度默认100
  • max-connections:最大可被连接数10000
  • max-threads:最大工作线程数200
  • min-spare-threads:最小工作线程数,10

可以通过修改上述属性,添加到application.properties中

//增加等待队列长度
server.tomcat.accept-count=1000
//增加最大工作线程数
server.tomcat.max-threads=250
server.tomcat.min-spare-threads=100     

2.弊端

在增加线程池中线程的同时,也要开启keep-alive,保证同一主机发送请求时不会重复建立连接(重复建立连接会增加资源的损耗),开启keep-alive的同时也要防止对网站的恶意攻击,就比如不停的恶意请求服务器,占用服务器资源,这里仅仅靠SpringBoot中提供的tomcat默认配置是不够的,因此就需要对使用的tomcat容器进行个性化开发,使之符合我们系统的要求。

2.1 如何定制化容器

我们可以在spring官网的文档上得到答案:spring官网
图片说明
这里写的明明白白,首先看看自动配置里面有没有那个属性,然后再考虑自己定制化开发。当然,这里我们已经考虑好了。
SpringBoot2.0之后都是用实现WebServerFactoryCustomizer接口来完成定制化开发的。

2.2 定制我们需要的tomcat容器

//当Sping容器内没有TomcatEmbeddedServletContainerFactory这个bean时,会把此bean加载进spring容器中
@Component
public class WebServerConfiguration implements WebServerFactoryCustomizer<ConfigurableWebServerFactory>{
    @Override
    public void customize(ConfigurableWebServerFactory factory) {
        //使用对应工厂类提供给我们的接口定制化我们的tomcat connector
        ((TomcatServletWebServerFactory)factory).addConnectorCustomizers(new TomcatConnectorCustomizer() {
            @Override
            public void customize(Connector connector) {
                Http11NioProtocol protocolHandler = (Http11NioProtocol)connector.getProtocolHandler();

                //定制化keepalivetimeout,设置30秒内没有请求则服务端自动断开keepalive链接
                protocolHandler.setKeepAliveTimeout(30000);

                //设置当客户端发送超过10000个请求则自动断开keepalive链接
                protocolHandler.setMaxKeepAliveRequests(10000);

            }
        });
    }
}

将工厂新增定制Connector,使用Http11NioProtocol(这个也可以讲一下),设置keepalivetimeout和setMaxKeepAliveRequests,就完成了我们的定制。

SpringBoot程序启动的时候先加载默认配置,然后加载application.properties中的配置,再将这个component中的配置加载到程序中,所以不用担心配置了属性但是不加载的问题。

这样就完成了我们Tomcat容器的定制化操作,设置了keepalive超时时间和请求数,保证了系统的稳定性。

全部评论

相关推荐

HR_丸山彩同学:你的项目描述里,系统设计讲了很多:MemCube是什么、三级存储架构怎么设计、四种遗忘策略分别是什么。这些面试的时候讲没问题,但简历上不需要这么细。 简历要突出的是影响力,不是实现细节。面试官看简历的时候想知道的是「这个项目有多大价值」,不是「这个项目具体怎么实现的」。实现细节是面试时候聊的 怎么改:技术细节可以精简为一句「采用三级存储架构+四种遗忘策略」,把省出来的篇幅用来写影响力。比如:项目有没有开源?有没有写成技术博客?有没有被别人使用过? 校园经历没有任何信息量,任何人都可以写这句话,写了等于没写。更关键的是,你投的是技术岗,校园活动经历本来就不是加分项。如果非要写,必须写出具体的数字和成果。如果你没有这些数字,那就老老实实删掉 「端到端耗时缩减30-40%」要给出确切数字和绝对值。从1000ms降到600ms是降了40%,从100ms降到60ms也是降了40%,但这两个含义完全不一样。其他也是,涉及到数据,准备好证据,口径统一,面试会问 「熟练」「熟悉」「了解」混在一起用,读起来很乱。而且「了解前端需求」最好改成「具备前后端协作经验」
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务