压测和Http长链接
1.背景
一般进行压测的时候,通常是一台施压机进行压测,这其中可能会存在施压机端口耗尽,导致压测性能降低的问题.本文针对最普通的场景进行说明(施压机直接压服务端代码):
1.1 一条TCP链接
一条完整的TCP链接有四个要素组成
- 源地址IP
- 源地址端口
- 目标地址ip
- 目标地址端口
服务端的ip和端口是固定,源地址的ip也是固定的,只有源地址的端口是可以变的,而源端口的数量又是有限的.我们再来看下什么是TimeWait:
1.2 什么是TimeWait
TimeWait是tcp四次挥手中的最后一部分,如下图所示
这部分的作用就是等待客户端可能丢失的ack事件,在linux中可以通过cat /proc/sys/net/ipv4/tcp_fin_timeout查看具体的时间.
1.3 什么是端口耗尽
有了前面两个小节的知识,再来看下为什么端口会被耗尽,从而影响压测的性能.
假设施压机全部可用的端口数为60000个,其中TimeWait的时间为120秒,也就是说在这120秒的时间内,端口是无法启用的.那么60000/120=5000,也就是说,客户端和服务端最大建立链接的速度是500次/秒**[1]**.
1.4 解决办法
解决办法就是利用复用tcp链接,如下图所示**[3]**
在http1.1协议中是默认开启长链接的,而在http1.0中需要在http Header中携带Connection:Keep-alive.其中KeepAlive有两个参数**[2]**,如下图所示:
timeout=5:表示超时时间为5s
max=1000:表示这条http链接最大可以服务的请求数
2. 实际压测
2.1 压测代码
在进行实际操作的时候,发现http链接并没有进行复用,为了简单起见,我这里用压测ok接口来进行说明.压测机的压测代码,使用的是 HttpClient4,
HttpGet get = new HttpGet("http://127.0.0.1:8088/ok");
PoolingHttpClientConnectionManager connManager
= new PoolingHttpClientConnectionManager();
connManager.setDefaultMaxPerRoute(1);
connManager.setMaxTotal(1);//最大链接数
CloseableHttpClient client = HttpClients.custom()
.setKeepAliveStrategy(myStrategy)
.setConnectionManager(connManager)
.setConnectionTimeToLive(80, TimeUnit.SECONDS)
.build();
最大链接数为1,keepAlive的策略为:
public static ConnectionKeepAliveStrategy myStrategy = new ConnectionKeepAliveStrategy() {
<