SpringBoot高并发调优

1.建立连接超时时间,单位毫秒【它会同时配置protocol的KeepAliveTimeout和protocol的ConnectionTimeout两个参数】

server.connection-timeout=20000

2.Http服务(Tcp协议Socket服务)的最大连接数(其实可以有更大,毕竟一台机子上可以有6万多个TCP端口

【注意请求来了是直接会占用maxConnections不会说先到backlog里排队再分配connections,因为自己这边吧backlog设置成30,maxConnections 3W,那么如果都要先在backlog里排队等待分配,显然

开启3000个线程且循环8次肯定backlog被撑爆了会拒绝接受连接,但是并没有报错,说明连接请求是直接连接而不是需要先在backlog里】

server.tomcat.max-connections=10000

3.Http服务(Tcp服务)连接的backlog(类似线程池里的等待队列)【好吧,Jmeter报错Address already in  use: connect是JMeter自己报的错误,即JMeter所在的系统也是不允许一个进程同时使用很多端口的

,所以开了keepalive超过这么多的请求数的时候就被拒绝了,而关了keepalive则不会出现这个问题,因为请求结束就释放了端口所以不会造成超过这么多次请求的情况,windows可以通过配置注册表解决:https://www.cnblogs.com/zhengna/p/10640620.html】

【有用,这边设置maxConnections是50,然后backlog是3W,而有3000个线程且循环10次,如果backlog没用百分百挂了;不过由于maxConnections很小,所以maxThreads再大也没用,因为最多就是同时处理50个请求,因此最多只需要50个线程;

所以线程数量可以和maxConnections保持一定的比例,它俩是很关联的;这里的吞吐量就是这个意思,处理3W个请求,但是由于maxConnections的原因只能一点一点处理,所以处理完毕花费了很久,因此tps很低】

【反正和三个配置有关,超时设置,keepalive设置和Linux允许进程最大连接数;因为如果有keepalive那么会导致进程占用的连接得不到释放,最终就出现了地址被占用的情况】

server.tomcat.accept-count=3000

4.tomcat处理请求时的线程池的最大线程数【注意,这个最好不要超过800,最大也就2000的样子,因为线程切换是会花费时间的,尽管增大了最大线程数可以防止同时来了很多请求导致处理很多请求没法得到线程处理的问题,但是线程数太大即便每个请求都得到了处理但是由于切换太频繁会浪费很多时间有时候tps反而更小;具体配多少还是要看qps是多少,然后请求的接口是CPU密集型还是IO密集型,IO等待多久都是有关系的,因此很难确定一个不变的正确的值;我这边反正是同时开启3000个请求循环10次,用800个线程和2000个线程最终的tps差不多;然后换成400的maxThreads tps居然比800的稍微高一点,200的和800的差不多,从测试结果来看400比较合适】

server.tomcat.max-threads=400

5.tomcat处理请求时的线程池最大核心线程数(八核的用9就够了,一般是核数+1)

server.tomcat.min-spare-threads=17

6.处理请求超时时间(即接口内部的业务处理不能超过这个时间),单位毫秒【好吧,这个配置也不像网上说的是请求处理超时时间,我这边在接口里sleep了足够的秒数也没看报错,还是说这个只适用于特殊请求的超时?(看名字好像是异步请求)】

# 似乎是AsyncContext asyncContext = httpServletRequest.startAsync();这种方式处理接口请求的时候的超时?【经过测试也不是,所以这是个bug?】

spring.mvc.async.request-timeout=20000

注意上面这个参数没有找到在代码里配置对应的配置值,它不是protocol.setKeepAliveTimeout(..)的配置值,也不是connector.setAsyncTimeout(..)的配置值,不知道对应什么代码配置;

还可以通过@Bean ServletWebServerFactory servletContainerFactory() {...}里面的connector和protocol来配置【由于用的是tomcat,所以是创建TomcatServletWebServerFactory】,可以通过TomcatWebServer来验证;

但是这种方式配置的maxThreads和minSpareThreads和maxConnections和acceptCount均没有生效【莫非ServletWebServerFactory要换成EmbeddedServletContainerFactory?】(但是用的protocol确实是自定义配置的protocol,然而这四个属性被什么地方的代码给重置了);

再进一步看了代码,protocol.setMaxThreads(..)其实是对其内部的endpoint.setMaxThreads,get也是这样,所以说是这个protocol内部引用的endpoint发生了改变?导致之前的set无效?

在TomcatServletWebServerFactory的配置过程里:

1.connector的protocol的keepAliveTimeout默认值是60000(60秒)【这个应该是客户端请求如果设置可keepalive为True,即保持长连接,则服务端http1.1版本以上是默认支持的,这里则是配置服务端对客户端请求如果没有数据过来继续保持长连接的时间】

2.protocol的maxKeepAliveRequests默认值是100【没有找到对应的配置key】【这个则是允许同时保持长连接的连接数/请求数】

3.protocol的maxThreads默认值是200(但是设置没有生效,版本是SpringBoot2.1.6.RELEASE)

4.protocol的minSpareThreads默认值是10(设置未生效)

5.protocol的maxConnections默认值是10000(设置未生效)

6.protocol的connectionTimeout默认值是60000(设置未生效)

7.connector的asyncTimeout默认值是30000(这个是用request.startAsync()方式处理请求时的超时时间)【没有找到对应的配置key】

这些配置里没有找到和spring.mvc.async.request-timeout对应的配置;

注意,可以用@Bean ServletWebServerFactory ...和application.properties共同配置来实现所有配置完成:

1.之前如果只用application.properties配置server.connection-timeout会同时生效于ConnectionTimeout和KeepAliveTimeout,如果在代码里配置了则KeepaliveTimeout以代码里的为准,但是connectionTimeout还是按配置的为准(哪怕代码里配置了)

2.connector的asyncTimeout在配置文件里没法配置,可以用代码配置;

3.protocol的maxKeepaliveRequests在配置文件里也没法配置,也可以用代码配置;

重要:SpringBoot里用的ApplicationContext是ServletWebServerApplicationContext,通过这个可以获取到WebServer对象,然后通过它来测试自己做的一些配置是否成功;

注意,连接超时是指发送了连接请求没有回应才是连接超时,在backlog里并不会造成连接超时;

连接超时是服务端能设置,客户端也能设置的,它们的值可以不同,比如客户端是10秒,发现心跳包10秒都没有回应,那么客户端主动抛异常,而服务端如果是8s,那么它也是会发送心跳包给客户端的超时没有回应也是抛异常;

tps就是吞吐量,即每秒处理的请求数量(包括响应),如820.7/sec表示某次压力测试下(开启了多少线程,每个线程循环多少次)平均每秒处理完毕多少请求;(这个其实如果是多台电脑一起发起请求tps会更高一点)

这里的测试结果不能看第一轮,因为第一轮项目刚启动所以会比较慢;

原文地址:https://www.cnblogs.com/silentdoer/p/12671188.html