发现并发容器问题
对单接口进行6000线程压测,每个线程请求5次,线程在5秒内创建完毕,当进行一半的时候,已经出现了请求响应时间过大及其错误率达到了43%。这个并发容量对于配置比较好点的服务器相对来说有点弱。
深入springboot底层了解原因在springboot官方文档中提到了关于元数据的配置
可以看到,关于我们最常用的设置项目的端口的默认配置就在其中。
默认内嵌tomcat配置1、server.tomcat.accept-count:等待队列长度,当可分配的线程数全部用完之后,后续的请求将进入等待队列等待,等待队列满后则拒绝处理,默认100。
2、server.tomcat.max-connections:最大可被连接数,默认10000
3、server.tomcat.max-threads:最大工作线程数,默认200,
4、server.tomcat.min-spare-threads:最小工作线程数,初始化分配线程数,默认10
默认配置下,连接超过10000后会出现拒绝连接情况
默认配置下,触发的请求超过200+100后拒绝处理(最大工作线程数+等待队列长度)
这些元数据spring当然提供了外部配置功能
#更改内嵌tomcat参数server.port=8080## 等待队列长度,默认100。server.tomcat.accept-count=1000## 最大工作线程数,默认200。(4核8g内存,线程数经验值800,操作系统做线程之间的切换调度是有系统开销的,所以不是越多越好。)server.tomcat.max-threads=800## 最小工作空闲线程数,默认10。(适当增大一些,以便应对突然增长的访问量)server.tomcat.min-spare-threads=100
springboot内置tomcat,在默认设置中,tomcat的最大线程数是200,最大连接数是10000。支持的并发量是指连接数,200个线程如何处理10000条连接的?
目前tomcat有三种处理连接的模式,一种是bio,一个线程只处理一个连接,另一种就是nio,一个线程处理多个连接。由于http请求不会太耗时,而且多个连接一般不会同时来消息,所以一个线程处理多个连接没有太大问题。
还有一种是apr模式,后续会详细介绍一下tomcat的这三种模式,这里不做深入讨论。
tomcat启动的时候,可以通过log看到connector使用的是哪一种运行模式:
starting protocolhandler [http-bio-8080]starting protocolhandler [http-nio-8080]starting protocolhandler [http-apr-8080]
默认值可以在spring-boot-autoconfigure-版本号.jar(比如:spring-boot-autoconfigure-2.1.0.release) 包中看到,解压反编译/web/serverproperties.class文件就可以看到默认配置。
定制化内嵌tomcat开发
关于keepalive在使用jmeter的http请求中默认是开启keepalive的
http的keepalive请求为当我们的客户端向我们的服务器发送http请求的时候,若带上了keepalive的请求头,则表明我们的http客户端希望跟服务端之间建立一个keepalive的连接,这个连接对应的用处就是说,向我们的服务端发送完对应的响应之后,我们的服务端不要立马断开连接,而是等待尝试复用连接。
此解决方案是用来解决http的一个响应,无状态,每次都要断开连接,新建连接所带来的一个耗时问题。
但如果说我们每个网页请求打开之后都跟服务端保持一个长连接,那我们服务端的连接数很快就会被用完了,因此再最早的http1.0的时候是没有设计keepalive的请求的,但是现在的http1.1加上keepalive请求,目的就是越来越多的移动端的设备,甚至于一些很复杂的网页交互,需要在用户浏览的过程当中,频繁的向服务端发送请求,因此,建立一个keepalive连接,并非为了压测的目的,而是真正的在应用场景上是有一些性能的好处的,无论是客户端还是服务端,在做一些网络通信的交互上面,无需每次都新建连接,断开连接,耗费tcp/ip建连的时间,而仅仅只需要发送数据即可。
但是这样的设计也会带来一些问题,如果说我们的服务端对keepalive的操作没有做任何限制 1.连接不做任何操作,不做任何响应,那这条连接对服务端来说就是一条费连接 2.有一些攻击者恶意利用keepalive连接向我们的服务端发送ddos的攻击,那服务端对应的连接只会成为攻击者攻击的后门,因此,为了安全,我们需要定制化tomcat开发
配置1、keepalivetimeout:多少毫秒后客户端不响应则断开keepalive
2、maxkeepaliverequests:多少次请求后keepalive断开失效
在springboot官方文档中提到了对内嵌容器的配置
//当spring容器内没有tomcatembeddedservletcontainerfactory这个bean时,会把bean加载进spring容器@configurationpublic class webserverconfiguration implements webserverfactorycustomizer<configurablewebserverfactory> {@overridepublic void customize(configurablewebserverfactory factory) {//使用对应工厂类提供给我们的接口定制化我们的tomcat connector((tomcatservletwebserverfactory)factory).addconnectorcustomizers(new tomcatconnectorcustomizer() {@overridepublic void customize(connector connector) {http11nioprotocol protocol= (http11nioprotocol) connector.getprotocolhandler();//定制keepalivetimeout,设置30秒内没有请求则服务器自动断开keepalive连接protocol.setkeepalivetimeout(30000);//当客户端发送超过10000个请求则自动断开keepalive连接protocol.setmaxkeepaliverequests(10000);}});}}
以上就是如何在springboot中内嵌tomcat并发容量的详细内容。