
以下脚本,证实 springboot 会话保持有问题
$ gobench -l :10902/mssm/v3/auth/api/customerVerify -c1 -t1
Dispatching 1 goroutines at 2021-08-03 16:44:42.211
10 / 10 [---------------------------------] 100.00% 1 p/s
Total requests: 26777 hits
OK requests: 26777 hits
Network failed(NF): 0 hits
Bad requests(!2xx)(BF): 0 hits
OK requests rate: 2677.678 hits/sec
Read throughput: 510.4KiB/sec
Write throughput: 472.2KiB/sec
Test time: 10s(2021-08-03 16:44:42.211-16:44:52.212)
Max X-Gobench-Seq: 26777
Real Connections: 268
$ gobench -l :5003/health -c1 -t1
Dispatching 1 goroutines at 2021-08-03 16:47:40.658
10 / 10 [-----------------------------------] 100.00% 1 p/s
Total requests: 79607 hits
OK requests: 79607 hits
Network failed(NF): 0 hits
Bad requests(!2xx)(BF): 0 hits
OK requests rate: 7960.749 hits/sec
Read throughput: 1.5MiB/sec
Write throughput: 1.2MiB/sec
Test time: 10s(2021-08-03 16:47:40.658-16:47:50.658)
Max X-Gobench-Seq: 79607
Real Connections: 1
抓包:GOLOG_STDOUT=true sudo -E httpdump -i any -port 10902 -verbose all -resp > a.txt

发现每一个连接,都是使用了100次(202中,200是包括100个请求100个响应,以及2个双向连接关闭),证实了是
关闭连接是tomcat主动发起的,也就是说,gobench发起了长连接,但是Tomcat却把它关闭了。
谷歌搜索 springboot tomcat keepalive,springboot maxKeepAliveRequests,找到解决方案,Tomcat关闭长连接的条件有2个:
Spring Boot Tomcat embed 中設置 Keep-Alive
此版本是基於 springboot 2.0.2.release,其他版本請自行測試
@Bean
public TomcatServletWebServerFactory tomcatServletWebServerFactory(){
TomcatServletWebServerFactory tomcatServletWebServerFactory = new TomcatServletWebServerFactory();
tomcatServletWebServerFactory.addConnectorCustomizers((connector)->{
ProtocolHandler protocolHandler = connector.getProtocolHandler();
if(protocolHandler instanceof Http11NioProtocol){
Http11NioProtocol http11NioProtocol = (Http11NioProtocol)protocolHandler;
http11NioProtocol.setKeepAliveTimeout(60000);//millisecond
http11NioProtocol.setMaxKeepAliveRequests(60000);
}
});
return tomcatServletWebServerFactory;
}
此版本是基於 springboot 1.5.6.release,其他版本請自行測試
@Bean
public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory(){
TomcatEmbeddedServletContainerFactory tomcatServletWebServerFactory = new TomcatEmbeddedServletContainerFactory();
tomcatServletWebServerFactory.addConnectorCustomizers((connector)->{
ProtocolHandler protocolHandler = connector.getProtocolHandler();
if(protocolHandler instanceof Http11NioProtocol){
Http11NioProtocol http11NioProtocol = (Http11NioProtocol)protocolHandler;
http11NioProtocol.setKeepAliveTimeout(60000);//millisecond
http11NioProtocol.setMaxKeepAliveRequests(60000);
}
});
return tomcatServletWebServerFactory;
}
HTTP 持久连接(HTTP persistent connection,也称作HTTP keep-alive 或HTTP connection reuse,翻译过来可以是保持连接或者连接复用)是使用同一个TCP 连接来发送和接收多个HTTP 请求/ 应答,而不是为每一个新的请求/ 应答打开新的连接的方式。
HTTP 协议采用“请求– 应答” 模式,当使用普通模式,即非KeepAlive 模式时,每个请求/ 应答客户和服务器都要新建一个连接,完成之后立即断开连接(HTTP 协议为无连接的协议),每次请求都会经过三次握手四次挥手过程,效率较低;当使用Keep-Alive
下图是每次新建连接和连接复用在通信模型上的区别:

在Http 1.0 中,Keep-Alive
Http1.1 以后,客户端(包括但不限于浏览器)发送请求时会在Header 中增加一个请求头 这样一来,客户端和服务器之间的HTTP 连接就会被保持,不会断开(断开方式下面介绍),当客户端发送另外一个请求时,就可以复用已建立的连接。Keep-AliveConnection: Keep-AliveConnection: Keep-Alive
现在的Http 协议基本都是Http 1.1 版本了,不太需要考虑1.0 的兼容问题
当然不是,Keep-Alive 也有自己的优缺点,并不是所有场景下都适用

